A game about forced loneliness, made by TACStudios
1using System; 2using System.Collections.Generic; 3using UnityObject = UnityEngine.Object; 4 5namespace Unity.VisualScripting 6{ 7 [DisableAnnotation] 8 public abstract class Macro<TGraph> : MacroScriptableObject, IMacro 9 where TGraph : class, IGraph, new() 10 { 11 [SerializeAs(nameof(graph))] 12 private TGraph _graph = new TGraph(); 13 14 [DoNotSerialize] 15 public TGraph graph 16 { 17 get => _graph; 18 set 19 { 20 if (value == null) 21 { 22 throw new InvalidOperationException("Macros must have a graph."); 23 } 24 25 if (value == graph) 26 { 27 return; 28 } 29 30 _graph = value; 31 } 32 } 33 34 [DoNotSerialize] 35 IGraph IMacro.graph 36 { 37 get => graph; 38 set => graph = (TGraph)value; 39 } 40 41 [DoNotSerialize] 42 IGraph IGraphParent.childGraph => graph; 43 44 public IEnumerable<object> GetAotStubs(HashSet<object> visited) 45 { 46 return graph.GetAotStubs(visited); 47 } 48 49 [DoNotSerialize] 50 bool IGraphParent.isSerializationRoot => true; 51 52 [DoNotSerialize] 53 UnityObject IGraphParent.serializedObject => this; 54 55 [DoNotSerialize] 56 private GraphReference _reference = null; 57 58 [DoNotSerialize] 59 protected GraphReference reference => _reference == null ? GraphReference.New(this, false) : _reference; 60 61 public bool isDescriptionValid 62 { 63 get => true; 64 set { } 65 } 66 67 protected override void OnBeforeDeserialize() 68 { 69 base.OnBeforeDeserialize(); 70 71 Serialization.NotifyDependencyDeserializing(this); 72 } 73 74 protected override void OnAfterDeserialize() 75 { 76 base.OnAfterDeserialize(); 77 78 Serialization.NotifyDependencyDeserialized(this); 79 } 80 81 public abstract TGraph DefaultGraph(); 82 83 IGraph IGraphParent.DefaultGraph() 84 { 85 return DefaultGraph(); 86 } 87 88 // This seems to fix the legendary undo bug! 89 // https://support.ludiq.io/communities/5/topics/4434-undo-bug-isolated 90 // The issue seems to be that newly created assets don't receive OnAfterDeserialize, 91 // and therefore never notify the dependencies system that they became available. 92 // Therefore, if any graph relied on a macro dependency (super unit, super state, flow state, state unit) 93 // that was created before a deserialization of that dependency (usually enter/exit play mode, restart Unity), 94 // it would silently never load, not throwing any error or warning along the way. 95 // For example, creating a new flow macro, dragging it to create a super node in another graph, 96 // then undoing, would corrupt the parent graph. 97 // Note: this *could* go in Awake, but OnEnable seems to be more reliable and consistent. Awake 98 // doesn't get called in play mode entry for example (but that doesn't matter because OnAfterDeserialize does anyway). 99 protected virtual void OnEnable() 100 { 101 Serialization.NotifyDependencyAvailable(this); 102 } 103 104 // ScriptableObjects actually call OnDisable not OnDestroy when unloaded ("goes out of scope"), 105 // so we need to unregister the dependency here. 106 // https://forum.unity.com/threads/scriptableobject-behaviour-discussion-how-scriptable-objects-work.541212/ 107 // The doc also guarantees it will be called before OnDestroy, so no need to repeat that in OnDestory. 108 protected virtual void OnDisable() 109 { 110 Serialization.NotifyDependencyUnavailable(this); 111 } 112 113 public GraphPointer GetReference() 114 { 115 return reference; 116 } 117 118 bool ISerializationDependency.IsDeserialized { get; set; } 119 } 120}