You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
6.2 KiB
199 lines
6.2 KiB
using System; |
|
using System.Collections; |
|
using System.Linq; |
|
using System.Collections.Generic; |
|
|
|
using UnityEditor; |
|
using UnityEngine; |
|
using UnityEngine.UIElements; |
|
using UnityEditor.ShaderGraph.Drawing; |
|
|
|
using GraphDataStore = UnityEditor.ShaderGraph.DataStore<UnityEditor.ShaderGraph.GraphData>; |
|
|
|
namespace UnityEditor.ShaderGraph |
|
{ |
|
class DummyChangeAction : IGraphDataAction |
|
{ |
|
void OnDummyChangeAction(GraphData m_GraphData) |
|
{ |
|
} |
|
|
|
public Action<GraphData> modifyGraphDataAction => OnDummyChangeAction; |
|
} |
|
|
|
struct SGControllerChangedEvent |
|
{ |
|
public ISGControlledElement target; |
|
public SGController controller; |
|
public IGraphDataAction change; |
|
|
|
private bool m_PropagationStopped; |
|
void StopPropagation() |
|
{ |
|
m_PropagationStopped = true; |
|
} |
|
|
|
public bool isPropagationStopped => m_PropagationStopped; |
|
} |
|
|
|
class SGControllerEvent |
|
{ |
|
ISGControlledElement target = null; |
|
|
|
SGControllerEvent(ISGControlledElement controlledTarget) |
|
{ |
|
target = controlledTarget; |
|
} |
|
} |
|
|
|
abstract class SGController |
|
{ |
|
public bool m_DisableCalled = false; |
|
|
|
protected IGraphDataAction DummyChange = new DummyChangeAction(); |
|
|
|
public virtual void OnDisable() |
|
{ |
|
if (m_DisableCalled) |
|
Debug.LogError(GetType().Name + ".Disable called twice"); |
|
|
|
m_DisableCalled = true; |
|
foreach (var element in allChildren) |
|
{ |
|
UnityEngine.Profiling.Profiler.BeginSample(element.GetType().Name + ".OnDisable"); |
|
element.OnDisable(); |
|
UnityEngine.Profiling.Profiler.EndSample(); |
|
} |
|
} |
|
|
|
internal void RegisterHandler(ISGControlledElement handler) |
|
{ |
|
//Debug.Log("RegisterHandler of " + handler.GetType().Name + " on " + GetType().Name ); |
|
|
|
if (m_EventHandlers.Contains(handler)) |
|
Debug.LogError("Handler registered twice"); |
|
else |
|
{ |
|
m_EventHandlers.Add(handler); |
|
|
|
NotifyEventHandler(handler, DummyChange); |
|
} |
|
} |
|
|
|
internal void UnregisterHandler(ISGControlledElement handler) |
|
{ |
|
m_EventHandlers.Remove(handler); |
|
} |
|
|
|
protected void NotifyChange(IGraphDataAction changeAction) |
|
{ |
|
var eventHandlers = m_EventHandlers.ToArray(); // Some notification may trigger Register/Unregister so duplicate the collection. |
|
|
|
foreach (var eventHandler in eventHandlers) |
|
{ |
|
UnityEngine.Profiling.Profiler.BeginSample("NotifyChange:" + eventHandler.GetType().Name); |
|
NotifyEventHandler(eventHandler, changeAction); |
|
UnityEngine.Profiling.Profiler.EndSample(); |
|
} |
|
} |
|
|
|
void NotifyEventHandler(ISGControlledElement eventHandler, IGraphDataAction changeAction) |
|
{ |
|
SGControllerChangedEvent e = new SGControllerChangedEvent(); |
|
e.controller = this; |
|
e.target = eventHandler; |
|
e.change = changeAction; |
|
eventHandler.OnControllerChanged(ref e); |
|
if (e.isPropagationStopped) |
|
return; |
|
if (eventHandler is VisualElement) |
|
{ |
|
var element = eventHandler as VisualElement; |
|
eventHandler = element.GetFirstOfType<ISGControlledElement>(); |
|
while (eventHandler != null) |
|
{ |
|
eventHandler.OnControllerChanged(ref e); |
|
if (e.isPropagationStopped) |
|
break; |
|
eventHandler = (eventHandler as VisualElement).GetFirstAncestorOfType<ISGControlledElement>(); |
|
} |
|
} |
|
} |
|
|
|
public void SendEvent(SGControllerEvent e) |
|
{ |
|
var eventHandlers = m_EventHandlers.ToArray(); // Some notification may trigger Register/Unregister so duplicate the collection. |
|
|
|
foreach (var eventHandler in eventHandlers) |
|
{ |
|
eventHandler.OnControllerEvent(e); |
|
} |
|
} |
|
|
|
public abstract void ApplyChanges(); |
|
|
|
public virtual IEnumerable<SGController> allChildren |
|
{ |
|
get { return Enumerable.Empty<SGController>(); } |
|
} |
|
|
|
List<ISGControlledElement> m_EventHandlers = new List<ISGControlledElement>(); |
|
} |
|
|
|
abstract class SGController<T> : SGController |
|
{ |
|
GraphDataStore m_DataStore; |
|
protected GraphDataStore DataStore => m_DataStore; |
|
|
|
protected SGController(T model, GraphDataStore dataStore) |
|
{ |
|
m_Model = model; |
|
m_DataStore = dataStore; |
|
DataStore.Subscribe += ModelChanged; |
|
} |
|
|
|
protected abstract void RequestModelChange(IGraphDataAction changeAction); |
|
|
|
protected abstract void ModelChanged(GraphData graphData, IGraphDataAction changeAction); |
|
|
|
T m_Model; |
|
public T Model => m_Model; |
|
|
|
// Cleanup delegate association before destruction |
|
public void Cleanup() |
|
{ |
|
DataStore.Subscribe -= ModelChanged; |
|
} |
|
} |
|
|
|
abstract class SGViewController<ModelType, ViewModelType> : SGController<ModelType> |
|
{ |
|
protected SGViewController(ModelType model, ViewModelType viewModel, GraphDataStore graphDataStore) : base(model, graphDataStore) |
|
{ |
|
m_ViewModel = viewModel; |
|
try |
|
{ |
|
// Need ViewModel to be initialized before we call ModelChanged() [as view model might need to update] |
|
ModelChanged(DataStore.State, DummyChange); |
|
} |
|
catch (Exception e) |
|
{ |
|
Debug.Log("Failed to initialize View Controller of type: " + this.GetType() + " due to exception: " + e); |
|
} |
|
} |
|
|
|
// Holds data specific to the views this controller is responsible for |
|
ViewModelType m_ViewModel; |
|
public ViewModelType ViewModel => m_ViewModel; |
|
|
|
public override void ApplyChanges() |
|
{ |
|
foreach (var controller in allChildren) |
|
{ |
|
controller.ApplyChanges(); |
|
} |
|
} |
|
|
|
public virtual void Destroy() { } |
|
} |
|
}
|
|
|