208 lines
6.4 KiB
C#
208 lines
6.4 KiB
C#
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>(); }
|
|
}
|
|
|
|
protected 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()
|
|
{
|
|
if (m_DataStore == null)
|
|
return;
|
|
DataStore.Subscribe -= ModelChanged;
|
|
m_Model = default;
|
|
m_DataStore = null;
|
|
}
|
|
}
|
|
|
|
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 Dispose()
|
|
{
|
|
m_EventHandlers.Clear();
|
|
m_ViewModel = default;
|
|
}
|
|
}
|
|
}
|