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}