using System; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace Unity.VisualScripting { public abstract class Graph : IGraph { protected Graph() { elements = new MergedGraphElementCollection(); } public override string ToString() { return StringUtility.FallbackWhitespace(title, base.ToString()); } public abstract IGraphData CreateData(); public virtual IGraphDebugData CreateDebugData() { return new GraphDebugData(this); } public virtual void Instantiate(GraphReference instance) { // Debug.Log($"Instantiating graph {instance}"); foreach (var element in elements) { element.Instantiate(instance); } } public virtual void Uninstantiate(GraphReference instance) { // Debug.Log($"Uninstantiating graph {instance}"); foreach (var element in elements) { element.Uninstantiate(instance); } } #region Elements [SerializeAs(nameof(elements))] private List _elements = new List(); [DoNotSerialize] public MergedGraphElementCollection elements { get; } #endregion #region Metadata [Serialize] public string title { get; set; } [Serialize] [InspectorTextArea(minLines = 1, maxLines = 10)] public string summary { get; set; } #endregion #region Canvas [Serialize] public Vector2 pan { get; set; } [Serialize] public float zoom { get; set; } = 1; #endregion #region Serialization public IEnumerable deserializationDependencies => _elements.SelectMany(e => e.deserializationDependencies); public virtual void OnBeforeSerialize() { _elements.Clear(); _elements.AddRange(elements); } public void OnAfterDeserialize() { Serialization.AwaitDependencies(this); } public virtual void OnAfterDependenciesDeserialized() { elements.Clear(); // _elements.OrderBy(e => e.dependencyOrder) var sortedElements = ListPool.New(); foreach (var element in _elements) { sortedElements.Add(element); } sortedElements.Sort((a, b) => a.dependencyOrder.CompareTo(b.dependencyOrder)); foreach (var element in sortedElements) { try { if (!element.HandleDependencies()) { continue; } elements.Add(element); } catch (Exception ex) { Debug.LogWarning($"Failed to add element to graph during deserialization: {element}\n{ex}"); } } ListPool.Free(sortedElements); } #endregion #region Poutine public IEnumerable GetAotStubs(HashSet visited) { return elements .Where(element => !visited.Contains(element)) .Select(element => { visited.Add(element); return element; }) .SelectMany(element => element.GetAotStubs(visited)); } private bool prewarmed; public void Prewarm() { if (prewarmed) { return; } foreach (var element in elements) { element.Prewarm(); } prewarmed = true; } public virtual void Dispose() { foreach (var element in elements) { element.Dispose(); } } #endregion } }