Initial Commit

This commit is contained in:
Sebastian Cabrera 2021-08-02 05:44:37 -04:00
parent 53eb92e9af
commit 270ab7d11f
15341 changed files with 700234 additions and 0 deletions

View file

@ -0,0 +1,8 @@
namespace Unity.VisualScripting
{
public interface IGizmoDrawer
{
void OnDrawGizmos();
void OnDrawGizmosSelected();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6b9bf948c5f3f4f6ea4ece19bd2bfd19
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,4 @@
namespace Unity.VisualScripting
{
public interface ISingleton { }
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 20f1871733b204f68bf987b34eb48db9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,9 @@
using UnityObject = UnityEngine.Object;
namespace Unity.VisualScripting
{
public interface IUnityObjectOwnable
{
UnityObject owner { get; set; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4f83d432cc5404d9cb2fe02b5f7d66ff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,78 @@
using System;
using UnityEngine;
namespace Unity.VisualScripting
{
public abstract class LudiqBehaviour : MonoBehaviour, ISerializationCallbackReceiver
{
[SerializeField, DoNotSerialize] // Serialize with Unity, but not with FullSerializer.
protected SerializationData _data;
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
if (Serialization.isCustomSerializing)
{
return;
}
Serialization.isUnitySerializing = true;
try
{
OnBeforeSerialize();
_data = this.Serialize(true);
OnAfterSerialize();
}
catch (Exception ex)
{
// Don't abort the whole serialization thread because this one object failed
Debug.LogError($"Failed to serialize behaviour.\n{ex}", this);
}
Serialization.isUnitySerializing = false;
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (Serialization.isCustomSerializing)
{
return;
}
Serialization.isUnitySerializing = true;
try
{
object @this = this;
OnBeforeDeserialize();
_data.DeserializeInto(ref @this, true);
OnAfterDeserialize();
}
catch (Exception ex)
{
// Don't abort the whole deserialization thread because this one object failed
Debug.LogError($"Failed to deserialize behaviour.\n{ex}", this);
}
Serialization.isUnitySerializing = false;
}
protected virtual void OnBeforeSerialize() { }
protected virtual void OnAfterSerialize() { }
protected virtual void OnBeforeDeserialize() { }
protected virtual void OnAfterDeserialize() { }
protected virtual void ShowData()
{
_data.ShowString(ToString());
}
public override string ToString()
{
return this.ToSafeString();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 552f45a311fac42f8906935140290279
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,83 @@
using System;
using UnityEngine;
namespace Unity.VisualScripting
{
public abstract class LudiqScriptableObject : ScriptableObject, ISerializationCallbackReceiver
{
[SerializeField, DoNotSerialize] // Serialize with Unity, but not with FullSerializer.
protected SerializationData _data;
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
// Ignore the FullSerializer callback, but still catch the Unity callback
if (Serialization.isCustomSerializing)
{
return;
}
Serialization.isUnitySerializing = true;
try
{
OnBeforeSerialize();
_data = this.Serialize(true);
OnAfterSerialize();
}
catch (Exception ex)
{
// Don't abort the whole serialization thread because this one object failed
Debug.LogError($"Failed to serialize scriptable object.\n{ex}", this);
}
Serialization.isUnitySerializing = false;
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
// Ignore the FullSerializer callback, but still catch the Unity callback
if (Serialization.isCustomSerializing)
{
return;
}
Serialization.isUnitySerializing = true;
try
{
object @this = this;
OnBeforeDeserialize();
_data.DeserializeInto(ref @this, true);
OnAfterDeserialize();
UnityThread.EditorAsync(OnPostDeserializeInEditor);
}
catch (Exception ex)
{
// Don't abort the whole deserialization thread because this one object failed
Debug.LogError($"Failed to deserialize scriptable object.\n{ex}", this);
}
Serialization.isUnitySerializing = false;
}
protected virtual void OnBeforeSerialize() { }
protected virtual void OnAfterSerialize() { }
protected virtual void OnBeforeDeserialize() { }
protected virtual void OnAfterDeserialize() { }
protected virtual void OnPostDeserializeInEditor() { }
protected virtual void ShowData()
{
_data.ShowString(ToString());
}
public override string ToString()
{
return this.ToSafeString();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b257eddef63bb4088bc8cb60712c1801
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,10 @@
using System;
namespace Unity.VisualScripting
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public sealed class RequiresUnityAPIAttribute : Attribute
{
public RequiresUnityAPIAttribute() : base() { }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f2fa9a6dc08148cbad51c4e368c6a2f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityObject = UnityEngine.Object;
namespace Unity.VisualScripting
{
/// <remarks>
/// Does not support objects hidden with hide flags.
/// </remarks>
public static class SceneSingleton<T> where T : MonoBehaviour, ISingleton
{
static SceneSingleton()
{
instances = new Dictionary<Scene, T>();
attribute = typeof(T).GetAttribute<SingletonAttribute>();
if (attribute == null)
{
throw new InvalidImplementationException($"Missing singleton attribute for '{typeof(T)}'.");
}
}
private static Dictionary<Scene, T> instances;
private static readonly SingletonAttribute attribute;
private static bool persistent => attribute.Persistent;
private static bool automatic => attribute.Automatic;
private static string name => attribute.Name;
private static HideFlags hideFlags => attribute.HideFlags;
private static void EnsureSceneValid(Scene scene)
{
if (!scene.IsValid())
{
throw new InvalidOperationException($"Scene '{scene.name}' is invalid and cannot be used in singleton operations.");
}
}
public static bool InstantiatedIn(Scene scene)
{
EnsureSceneValid(scene);
if (Application.isPlaying)
{
return instances.ContainsKey(scene);
}
else
{
return FindInstances(scene).Length == 1;
}
}
public static T InstanceIn(Scene scene)
{
EnsureSceneValid(scene);
if (Application.isPlaying)
{
if (instances.ContainsKey(scene))
{
return instances[scene];
}
else
{
return FindOrCreateInstance(scene);
}
}
else
{
return FindOrCreateInstance(scene);
}
}
private static T[] FindInstances(Scene scene)
{
EnsureSceneValid(scene);
// Fails here on hidden hide flags
return UnityObject.FindObjectsOfType<T>().Where(o => o.gameObject.scene == scene).ToArray();
}
private static T FindOrCreateInstance(Scene scene)
{
EnsureSceneValid(scene);
var instances = FindInstances(scene);
if (instances.Length == 1)
{
return instances[0];
}
else if (instances.Length == 0)
{
if (automatic)
{
// Because DontDestroyOnLoad moves objects to another scene internally,
// the scene singleton system does not support persistence (which wouldn't
// make sense logically either!)
if (persistent)
{
throw new UnityException("Scene singletons cannot be persistent.");
}
// Create the parent game object with the proper hide flags
var singleton = new GameObject(name ?? typeof(T).Name);
singleton.hideFlags = hideFlags;
// Immediately move it to the proper scene so that Register can determine dictionary key
SceneManager.MoveGameObjectToScene(singleton, scene);
// Instantiate the component, letting Awake register the instance if we're in play mode
var instance = singleton.AddComponent<T>();
instance.hideFlags = hideFlags;
return instance;
}
else
{
throw new UnityException($"Missing '{typeof(T)}' singleton in scene '{scene.name}'.");
}
}
else // if (instances.Length > 1)
{
throw new UnityException($"More than one '{typeof(T)}' singleton in scene '{scene.name}'.");
}
}
public static void Awake(T instance)
{
Ensure.That(nameof(instance)).IsNotNull(instance);
var scene = instance.gameObject.scene;
EnsureSceneValid(scene);
if (instances.ContainsKey(scene))
{
throw new UnityException($"More than one '{typeof(T)}' singleton in scene '{scene.name}'.");
}
instances.Add(scene, instance);
}
public static void OnDestroy(T instance)
{
Ensure.That(nameof(instance)).IsNotNull(instance);
var scene = instance.gameObject.scene;
// If the scene is invalid, it has probably been unloaded already
// (for example the DontDestroyOnLoad pseudo-scene), so we can't
// access it. However, we'll need to check in the dictionary by
// value to remove the entry anyway.
if (!scene.IsValid())
{
foreach (var kvp in instances)
{
if (kvp.Value == instance)
{
instances.Remove(kvp.Key);
break;
}
}
return;
}
if (instances.ContainsKey(scene))
{
var sceneInstance = instances[scene];
if (sceneInstance == instance)
{
instances.Remove(scene);
}
else
{
throw new UnityException($"Trying to destroy invalid instance of '{typeof(T)}' singleton in scene '{scene.name}'.");
}
}
else
{
throw new UnityException($"Trying to destroy invalid instance of '{typeof(T)}' singleton in scene '{scene.name}'.");
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c2ec8389736ca49ecb53889bb7635509
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,167 @@
using System.Collections.Generic;
using UnityEngine;
using UnityObject = UnityEngine.Object;
namespace Unity.VisualScripting
{
/// <remarks>
/// Does not support objects hidden with hide flags.
/// </remarks>
public static class Singleton<T> where T : MonoBehaviour, ISingleton
{
static Singleton()
{
awoken = new HashSet<T>();
attribute = typeof(T).GetAttribute<SingletonAttribute>();
if (attribute == null)
{
throw new InvalidImplementationException($"Missing singleton attribute for '{typeof(T)}'.");
}
}
private static readonly SingletonAttribute attribute;
private static bool persistent => attribute.Persistent;
private static bool automatic => attribute.Automatic;
private static string name => attribute.Name;
private static HideFlags hideFlags => attribute.HideFlags;
private static readonly object _lock = new object();
private static readonly HashSet<T> awoken;
private static T _instance;
public static bool instantiated
{
get
{
lock (_lock)
{
if (Application.isPlaying)
{
return _instance != null;
}
else
{
return FindInstances().Length == 1;
}
}
}
}
public static T instance
{
get
{
lock (_lock)
{
if (Application.isPlaying)
{
if (_instance == null)
{
Instantiate();
}
return _instance;
}
else
{
return Instantiate();
}
}
}
}
private static T[] FindInstances()
{
// Fails here on hidden hide flags
return UnityObject.FindObjectsOfType<T>();
}
public static T Instantiate()
{
lock (_lock)
{
var instances = FindInstances();
if (instances.Length == 1)
{
_instance = instances[0];
}
else if (instances.Length == 0)
{
if (automatic)
{
// Create the parent game object with the proper hide flags
var singleton = new GameObject(name ?? typeof(T).Name);
singleton.hideFlags = hideFlags;
// Instantiate the component, letting Awake assign the real instance variable
var _instance = singleton.AddComponent<T>();
_instance.hideFlags = hideFlags;
// Sometimes in the editor, for example when creating a new scene,
// AddComponent seems to call Awake add a later frame, making this call
// fail for exactly one frame. We'll force-awake it if need be.
Awake(_instance);
// Make the singleton persistent if need be
if (persistent && Application.isPlaying)
{
UnityObject.DontDestroyOnLoad(singleton);
}
}
else
{
throw new UnityException($"Missing '{typeof(T)}' singleton in the scene.");
}
}
else if (instances.Length > 1)
{
throw new UnityException($"More than one '{typeof(T)}' singleton in the scene.");
}
return _instance;
}
}
public static void Awake(T instance)
{
Ensure.That(nameof(instance)).IsNotNull(instance);
if (awoken.Contains(instance))
{
return;
}
if (_instance != null)
{
throw new UnityException($"More than one '{typeof(T)}' singleton in the scene.");
}
_instance = instance;
awoken.Add(instance);
}
public static void OnDestroy(T instance)
{
Ensure.That(nameof(instance)).IsNotNull(instance);
if (_instance == instance)
{
_instance = null;
}
else
{
throw new UnityException($"Trying to destroy invalid instance of '{typeof(T)}' singleton.");
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f45eb13c750f34cc497852f2312d5937
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,19 @@
using System;
using UnityEngine;
namespace Unity.VisualScripting
{
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public sealed class SingletonAttribute : Attribute
{
public SingletonAttribute()
{
HideFlags = HideFlags.None;
}
public bool Persistent { get; set; }
public bool Automatic { get; set; }
public HideFlags HideFlags { get; set; }
public string Name { get; set; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 733f8c95b5e9f45d69dc6e292d5367c8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,33 @@
using UnityEngine;
using UnityObject = UnityEngine.Object;
namespace Unity.VisualScripting
{
public static class UnityObjectOwnershipUtility
{
public static void CopyOwner(object source, object destination)
{
var destinationOwned = destination as IUnityObjectOwnable;
if (destinationOwned != null)
{
destinationOwned.owner = GetOwner(source);
}
}
public static void RemoveOwner(object o)
{
var sourceOwned = o as IUnityObjectOwnable;
if (sourceOwned != null)
{
sourceOwned.owner = null;
}
}
public static UnityObject GetOwner(object o)
{
return (o as Component)?.gameObject ?? (o as IUnityObjectOwnable)?.owner;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 06cf7033246114febb1d5c2f284969a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,26 @@
using System;
using System.Threading;
using UnityEngine;
namespace Unity.VisualScripting
{
public static class UnityThread
{
public static Thread thread = Thread.CurrentThread;
public static Action<Action> editorAsync;
public static bool allowsAPI => !Serialization.isUnitySerializing && Thread.CurrentThread == thread;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void RuntimeInitialize()
{
thread = Thread.CurrentThread;
}
public static void EditorAsync(Action action)
{
editorAsync?.Invoke(action);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fa8d42551757546b2b05a1aa9c246a4a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: