A game about forced loneliness, made by TACStudios
1using System.Collections.Generic; 2using UnityEngine; 3using UnityObject = UnityEngine.Object; 4 5namespace Unity.VisualScripting 6{ 7 public abstract class Machine<TGraph, TMacro> : LudiqBehaviour, IMachine 8 where TGraph : class, IGraph, new() 9 where TMacro : Macro<TGraph> 10 { 11 protected Machine() 12 { 13 nest.nester = this; 14 nest.source = GraphSource.Macro; 15 } 16 17 [Serialize] 18 public GraphNest<TGraph, TMacro> nest { get; private set; } = new GraphNest<TGraph, TMacro>(); 19 20 [DoNotSerialize] 21 IGraphNest IGraphNester.nest => nest; 22 23 // We use our own alive and enabled bools which are thread safe. 24 // Alive is true in Awake and OnEnable, and becomes false in OnDestroy. 25 // Enabled is not true during Awake, to avoid double OnEnable triggering due to GraphNest delegates 26 // See: https://support.ludiq.io/communities/5/topics/1971-a/ 27 [DoNotSerialize] 28 private bool _alive; 29 30 [DoNotSerialize] 31 private bool _enabled; 32 33 [DoNotSerialize] 34 private GameObject threadSafeGameObject; 35 36 [DoNotSerialize] 37 GameObject IMachine.threadSafeGameObject => threadSafeGameObject; 38 39 [DoNotSerialize] 40 private bool isReferenceCached; 41 42 [DoNotSerialize] 43 private GraphReference _reference; 44 45 [DoNotSerialize] 46 protected GraphReference reference => isReferenceCached ? _reference : GraphReference.New(this, false); 47 48 [DoNotSerialize] 49 protected bool hasGraph => reference != null; 50 51 [DoNotSerialize] 52 public TGraph graph => nest.graph; 53 54 [DoNotSerialize] 55 public IGraphData graphData { get; set; } 56 57 [DoNotSerialize] 58 bool IGraphParent.isSerializationRoot => true; 59 60 [DoNotSerialize] 61 UnityObject IGraphParent.serializedObject 62 { 63 get 64 { 65 switch (nest.source) 66 { 67 case GraphSource.Macro: return nest.macro; 68 case GraphSource.Embed: return this; 69 default: throw new UnexpectedEnumValueException<GraphSource>(nest.source); 70 } 71 } 72 } 73 74 [DoNotSerialize] 75 IGraph IGraphParent.childGraph => graph; 76 77 public IEnumerable<object> GetAotStubs(HashSet<object> visited) 78 { 79 return nest.GetAotStubs(visited); 80 } 81 82 public bool isDescriptionValid 83 { 84 get => true; 85 set { } 86 } 87 88 protected virtual void Awake() 89 { 90 _alive = true; 91 threadSafeGameObject = gameObject; 92 93 nest.afterGraphChange += CacheReference; 94 nest.beforeGraphChange += ClearCachedReference; 95 96 CacheReference(); 97 98 if (graph != null) 99 { 100 graph.Prewarm(); 101 InstantiateNest(); 102 } 103 } 104 105 protected virtual void OnEnable() 106 { 107 _enabled = true; 108 } 109 110 protected virtual void OnInstantiateWhileEnabled() 111 { 112 } 113 114 protected virtual void OnUninstantiateWhileEnabled() 115 { 116 } 117 118 protected virtual void OnDisable() 119 { 120 _enabled = false; 121 } 122 123 protected virtual void OnDestroy() 124 { 125 ClearCachedReference(); 126 127 if (graph != null) 128 { 129 UninstantiateNest(); 130 } 131 132 threadSafeGameObject = null; 133 _alive = false; 134 } 135 136 protected virtual void OnValidate() 137 { 138 threadSafeGameObject = gameObject; 139 } 140 141 public GraphPointer GetReference() 142 { 143 return reference; 144 } 145 146 private void CacheReference() 147 { 148 _reference = GraphReference.New(this, false); 149 isReferenceCached = true; 150 } 151 152 private void ClearCachedReference() 153 { 154 if (_reference != null) 155 { 156 _reference.Release(); 157 _reference = null; 158 } 159 } 160 161 public virtual void InstantiateNest() 162 { 163 if (_alive) 164 { 165 GraphInstances.Instantiate(reference); 166 } 167 168 if (_enabled) 169 { 170 if (UnityThread.allowsAPI) 171 { 172 OnInstantiateWhileEnabled(); 173 } 174 else 175 { 176 Debug.LogWarning($"Could not run instantiation events on {this.ToSafeString()} because the Unity API is not available.\nThis can happen when undoing / redoing a graph source change.", this); 177 } 178 } 179 } 180 181 public virtual void UninstantiateNest() 182 { 183 if (_enabled) 184 { 185 if (UnityThread.allowsAPI) 186 { 187 OnUninstantiateWhileEnabled(); 188 } 189 else 190 { 191 Debug.LogWarning($"Could not run uninstantiation events on {this.ToSafeString()} because the Unity API is not available.\nThis can happen when undoing / redoing a graph source change.", this); 192 } 193 } 194 195 if (_alive) 196 { 197 var instances = GraphInstances.ChildrenOfPooled(this); 198 199 foreach (var instance in instances) 200 { 201 GraphInstances.Uninstantiate(instance); 202 } 203 204 instances.Free(); 205 } 206 } 207 208#if MODULE_ANIMATION_EXISTS 209 // Should be in EventMachine logically, but kept here for legacy compatibility. 210 public virtual void TriggerAnimationEvent(AnimationEvent animationEvent) 211 { 212 } 213#endif 214 215 // Should be in EventMachine logically, but kept here for legacy compatibility. 216 public virtual void TriggerUnityEvent(string name) 217 { 218 } 219 220 public abstract TGraph DefaultGraph(); 221 222 IGraph IGraphParent.DefaultGraph() => DefaultGraph(); 223 } 224}