A game about forced loneliness, made by TACStudios
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5 6namespace Unity.VisualScripting 7{ 8 public abstract class GraphElement<TGraph> : IGraphElement where TGraph : class, IGraph 9 { 10 [Serialize] 11 public Guid guid { get; set; } = Guid.NewGuid(); 12 13 // To minimize the amount of implementation needed, and simplify inversion of control, 14 // we provide instantiation routines that fit most types of elements in the right order and 15 // we provide implemented defaults for interfaces that the element could implement. 16 // Normally, an element shouldn't have to override instantiate or uninstantiate directly. 17 18 public virtual void Instantiate(GraphReference instance) 19 { 20 // Create the data for this graph, non-recursively, that is 21 // required for the nest instantiation, so we do it first. 22 if (this is IGraphElementWithData withData) 23 { 24 instance.data.CreateElementData(withData); 25 } 26 27 // Nest instantiation is a recursive operation that will 28 // call Instantiate on descendant graphs and elements. 29 // Because event listening will descend graph data recursively, 30 // we need to create it before. 31 if (this is IGraphNesterElement nester && nester.nest.graph != null) 32 { 33 GraphInstances.Instantiate(instance.ChildReference(nester, true)); 34 } 35 36 // StartListening is a recursive operation that will 37 // descend graphs recursively. It must be called after 38 // instantiation of all child graphs because it will require 39 // their data. The drawback with this approach is that it will be 40 // called at each step bubbling up, whereas it will only 41 // effectively trigger once we reach the top level. 42 // Traversal is currently O(n!) where n is the number of descendants, 43 // ideally it would be O(n) if only triggered from the root. 44 45 // => Listening has to be implemented by Bolt classes, because Graphs isn't aware of the event system 46 } 47 48 public virtual void Uninstantiate(GraphReference instance) 49 { 50 // See above comments, in reverse order. 51 52 if (this is IGraphNesterElement nester && nester.nest.graph != null) 53 { 54 GraphInstances.Uninstantiate(instance.ChildReference(nester, true)); 55 } 56 57 if (this is IGraphElementWithData withData) 58 { 59 instance.data.FreeElementData(withData); 60 } 61 } 62 63 public virtual void BeforeAdd() { } 64 65 public virtual void AfterAdd() 66 { 67 var instances = GraphInstances.OfPooled(graph); 68 69 foreach (var instance in instances) 70 { 71 Instantiate(instance); 72 } 73 74 instances.Free(); 75 } 76 77 public virtual void BeforeRemove() 78 { 79 var instances = GraphInstances.OfPooled(graph); 80 81 foreach (var instance in instances) 82 { 83 Uninstantiate(instance); 84 } 85 86 instances.Free(); 87 88 Dispose(); 89 } 90 91 public virtual void AfterRemove() { } 92 93 public virtual void Dispose() { } 94 95 protected void InstantiateNest() 96 { 97 var nester = (IGraphNesterElement)this; 98 99 if (graph == null) 100 { 101 return; 102 } 103 104 var instances = GraphInstances.OfPooled(graph); 105 106 foreach (var instance in instances) 107 { 108 GraphInstances.Instantiate(instance.ChildReference(nester, true)); 109 } 110 111 instances.Free(); 112 } 113 114 protected void UninstantiateNest() 115 { 116 var nester = (IGraphNesterElement)this; 117 118 var instances = GraphInstances.ChildrenOfPooled(nester); 119 120 foreach (var instance in instances) 121 { 122 GraphInstances.Uninstantiate(instance); 123 } 124 125 instances.Free(); 126 } 127 128 #region Graph 129 130 [DoNotSerialize] 131 public virtual int dependencyOrder => 0; 132 133 public virtual bool HandleDependencies() => true; 134 135 [DoNotSerialize] 136 public TGraph graph { get; set; } 137 138 [DoNotSerialize] 139 IGraph IGraphElement.graph 140 { 141 get => graph; 142 set 143 { 144 Ensure.That(nameof(value)).IsOfType<TGraph>(value); 145 graph = (TGraph)value; 146 } 147 } 148 149 [DoNotSerialize] 150 IGraph IGraphItem.graph => graph; 151 152 #endregion 153 154 #region Poutine 155 156 public virtual IEnumerable<ISerializationDependency> deserializationDependencies => Enumerable.Empty<ISerializationDependency>(); 157 158 public virtual IEnumerable<object> GetAotStubs(HashSet<object> visited) 159 { 160 return Enumerable.Empty<object>(); 161 } 162 163 public virtual void Prewarm() { } 164 165 protected void CopyFrom(GraphElement<TGraph> source) { } 166 167 public override string ToString() 168 { 169 var sb = new StringBuilder(); 170 sb.Append(GetType().Name); 171 sb.Append("#"); 172 sb.Append(guid.ToString().Substring(0, 5)); 173 sb.Append("..."); 174 return sb.ToString(); 175 } 176 177 #endregion 178 179 public virtual AnalyticsIdentifier GetAnalyticsIdentifier() 180 { 181 throw new NotImplementedException(); 182 } 183 } 184}