using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using UnityEditor; using UnityObject = UnityEngine.Object; namespace Unity.VisualScripting { public abstract class GraphContext : IGraphContext where TGraph : class, IGraph where TCanvas : class, ICanvas { protected GraphContext(GraphReference reference) { Ensure.That(nameof(reference)).IsNotNull(reference); Ensure.That(nameof(reference.graph)).IsOfType(reference.graph); this.reference = reference; analyserProvider = new AnalyserProvider(reference); graphMetadata = Metadata.Root().StaticObject(reference.graph); extensions = this.Extensions().ToList().AsReadOnly(); sidebarPanels = SidebarPanels().ToList().AsReadOnly(); } public GraphReference reference { get; } public AnalyserProvider analyserProvider { get; } public TCanvas canvas => (TCanvas)graph.Canvas(); ICanvas IGraphContext.canvas => canvas; public GraphSelection selection => canvas.selection; public TGraph graph => (TGraph)reference.graph; IGraph IGraphContext.graph => graph; public Metadata graphMetadata { get; } public Metadata selectionMetadata => selection.Count == 1 ? ElementMetadata(selection.Single()) : null; public Metadata ElementMetadata(IGraphElement element) { // Static object is faster than indexer // return graphMetadata[nameof(IGraph.elements)].Indexer(element.guid).Cast(element.GetType()); return graphMetadata[nameof(IGraph.elements)].StaticObject(element); } public ReadOnlyCollection extensions { get; } IEnumerable IGraphContext.extensions => extensions; public virtual string windowTitle => "Graph"; protected virtual IEnumerable SidebarPanels() => Enumerable.Empty(); public ReadOnlyCollection sidebarPanels { get; } IEnumerable IGraphContext.sidebarPanels => sidebarPanels; public bool isPrefabInstance => reference.serializedObject?.IsConnectedPrefabInstance() ?? false; #region Lifecycle public virtual void Dispose() { // Manually free the providers so that the // disposable decorators free their event handlers analyserProvider?.FreeAll(); } public void BeginEdit(bool disablePrefabInstance = true) { LudiqEditorUtility.editedObject.BeginOverride(reference.serializedObject); LudiqGraphsEditorUtility.editedContext.BeginOverride(this); EditorGUI.BeginDisabledGroup(disablePrefabInstance && isPrefabInstance); EditorGUI.BeginChangeCheck(); } public void EndEdit() { if (EditorGUI.EndChangeCheck()) { DescribeAndAnalyze(); } EditorGUI.EndDisabledGroup(); LudiqGraphsEditorUtility.editedContext.EndOverride(); LudiqEditorUtility.editedObject.EndOverride(); } public void DescribeAndAnalyze() { foreach (var element in graph.elements) { if (element.HasDescriptor()) { element.Describe(); } } graph.Describe(); analyserProvider.AnalyzeAll(); reference.parent.Describe(); } #endregion } }