A game about forced loneliness, made by TACStudios
1using System; 2using System.Collections; 3using System.Linq; 4using System.Collections.Generic; 5 6using UnityEditor; 7using UnityEngine; 8using UnityEngine.UIElements; 9using UnityEditor.ShaderGraph.Drawing; 10 11using GraphDataStore = UnityEditor.ShaderGraph.DataStore<UnityEditor.ShaderGraph.GraphData>; 12 13namespace UnityEditor.ShaderGraph 14{ 15 class DummyChangeAction : IGraphDataAction 16 { 17 void OnDummyChangeAction(GraphData m_GraphData) 18 { 19 } 20 21 public Action<GraphData> modifyGraphDataAction => OnDummyChangeAction; 22 } 23 24 struct SGControllerChangedEvent 25 { 26 public ISGControlledElement target; 27 public SGController controller; 28 public IGraphDataAction change; 29 30 private bool m_PropagationStopped; 31 void StopPropagation() 32 { 33 m_PropagationStopped = true; 34 } 35 36 public bool isPropagationStopped => m_PropagationStopped; 37 } 38 39 class SGControllerEvent 40 { 41 ISGControlledElement target = null; 42 43 SGControllerEvent(ISGControlledElement controlledTarget) 44 { 45 target = controlledTarget; 46 } 47 } 48 49 abstract class SGController 50 { 51 public bool m_DisableCalled = false; 52 53 protected IGraphDataAction DummyChange = new DummyChangeAction(); 54 55 public virtual void OnDisable() 56 { 57 if (m_DisableCalled) 58 Debug.LogError(GetType().Name + ".Disable called twice"); 59 60 m_DisableCalled = true; 61 foreach (var element in allChildren) 62 { 63 UnityEngine.Profiling.Profiler.BeginSample(element.GetType().Name + ".OnDisable"); 64 element.OnDisable(); 65 UnityEngine.Profiling.Profiler.EndSample(); 66 } 67 } 68 69 internal void RegisterHandler(ISGControlledElement handler) 70 { 71 //Debug.Log("RegisterHandler of " + handler.GetType().Name + " on " + GetType().Name ); 72 73 if (m_EventHandlers.Contains(handler)) 74 Debug.LogError("Handler registered twice"); 75 else 76 { 77 m_EventHandlers.Add(handler); 78 79 NotifyEventHandler(handler, DummyChange); 80 } 81 } 82 83 internal void UnregisterHandler(ISGControlledElement handler) 84 { 85 m_EventHandlers.Remove(handler); 86 } 87 88 protected void NotifyChange(IGraphDataAction changeAction) 89 { 90 var eventHandlers = m_EventHandlers.ToArray(); // Some notification may trigger Register/Unregister so duplicate the collection. 91 92 foreach (var eventHandler in eventHandlers) 93 { 94 UnityEngine.Profiling.Profiler.BeginSample("NotifyChange:" + eventHandler.GetType().Name); 95 NotifyEventHandler(eventHandler, changeAction); 96 UnityEngine.Profiling.Profiler.EndSample(); 97 } 98 } 99 100 void NotifyEventHandler(ISGControlledElement eventHandler, IGraphDataAction changeAction) 101 { 102 SGControllerChangedEvent e = new SGControllerChangedEvent(); 103 e.controller = this; 104 e.target = eventHandler; 105 e.change = changeAction; 106 eventHandler.OnControllerChanged(ref e); 107 if (e.isPropagationStopped) 108 return; 109 if (eventHandler is VisualElement) 110 { 111 var element = eventHandler as VisualElement; 112 eventHandler = element.GetFirstOfType<ISGControlledElement>(); 113 while (eventHandler != null) 114 { 115 eventHandler.OnControllerChanged(ref e); 116 if (e.isPropagationStopped) 117 break; 118 eventHandler = (eventHandler as VisualElement).GetFirstAncestorOfType<ISGControlledElement>(); 119 } 120 } 121 } 122 123 public void SendEvent(SGControllerEvent e) 124 { 125 var eventHandlers = m_EventHandlers.ToArray(); // Some notification may trigger Register/Unregister so duplicate the collection. 126 127 foreach (var eventHandler in eventHandlers) 128 { 129 eventHandler.OnControllerEvent(e); 130 } 131 } 132 133 public abstract void ApplyChanges(); 134 135 public virtual IEnumerable<SGController> allChildren 136 { 137 get { return Enumerable.Empty<SGController>(); } 138 } 139 140 protected List<ISGControlledElement> m_EventHandlers = new List<ISGControlledElement>(); 141 } 142 143 abstract class SGController<T> : SGController 144 { 145 GraphDataStore m_DataStore; 146 protected GraphDataStore DataStore => m_DataStore; 147 148 protected SGController(T model, GraphDataStore dataStore) 149 { 150 m_Model = model; 151 m_DataStore = dataStore; 152 DataStore.Subscribe += ModelChanged; 153 } 154 155 protected abstract void RequestModelChange(IGraphDataAction changeAction); 156 157 protected abstract void ModelChanged(GraphData graphData, IGraphDataAction changeAction); 158 159 T m_Model; 160 public T Model => m_Model; 161 162 // Cleanup delegate association before destruction 163 public void Cleanup() 164 { 165 if (m_DataStore == null) 166 return; 167 DataStore.Subscribe -= ModelChanged; 168 m_Model = default; 169 m_DataStore = null; 170 } 171 } 172 173 abstract class SGViewController<ModelType, ViewModelType> : SGController<ModelType> 174 { 175 protected SGViewController(ModelType model, ViewModelType viewModel, GraphDataStore graphDataStore) : base(model, graphDataStore) 176 { 177 m_ViewModel = viewModel; 178 try 179 { 180 // Need ViewModel to be initialized before we call ModelChanged() [as view model might need to update] 181 ModelChanged(DataStore.State, DummyChange); 182 } 183 catch (Exception e) 184 { 185 Debug.Log("Failed to initialize View Controller of type: " + this.GetType() + " due to exception: " + e); 186 } 187 } 188 189 // Holds data specific to the views this controller is responsible for 190 ViewModelType m_ViewModel; 191 public ViewModelType ViewModel => m_ViewModel; 192 193 public override void ApplyChanges() 194 { 195 foreach (var controller in allChildren) 196 { 197 controller.ApplyChanges(); 198 } 199 } 200 201 public virtual void Dispose() 202 { 203 m_EventHandlers.Clear(); 204 m_ViewModel = default; 205 } 206 } 207}