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.
288 lines
10 KiB
288 lines
10 KiB
using UnityEditor.Experimental.GraphView;
|
|
using UnityEngine.UIElements;
|
|
using UnityEngine;
|
|
using UnityEditor.VFX;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.Reflection;
|
|
|
|
using UnityObject = UnityEngine.Object;
|
|
|
|
namespace UnityEditor.VFX.UI
|
|
{
|
|
class VFXContextController : VFXNodeController
|
|
{
|
|
public new VFXContext model { get { return base.model as VFXContext; } }
|
|
|
|
private List<VFXBlockController> m_BlockControllers = new List<VFXBlockController>();
|
|
public ReadOnlyCollection<VFXBlockController> blockControllers
|
|
{
|
|
get { return m_BlockControllers.AsReadOnly(); }
|
|
}
|
|
|
|
protected List<VFXFlowAnchorController> m_FlowInputAnchors = new List<VFXFlowAnchorController>();
|
|
public ReadOnlyCollection<VFXFlowAnchorController> flowInputAnchors
|
|
{
|
|
get { return m_FlowInputAnchors.AsReadOnly(); }
|
|
}
|
|
|
|
protected List<VFXFlowAnchorController> m_FlowOutputAnchors = new List<VFXFlowAnchorController>();
|
|
public ReadOnlyCollection<VFXFlowAnchorController> flowOutputAnchors
|
|
{
|
|
get { return m_FlowOutputAnchors.AsReadOnly(); }
|
|
}
|
|
public char letter { get { return model.letter; } set { model.letter = value; } }
|
|
|
|
public override void OnDisable()
|
|
{
|
|
if (viewController != null)
|
|
{
|
|
UnregisterAnchors();
|
|
}
|
|
if (!object.ReferenceEquals(m_Data, null))
|
|
{
|
|
viewController.UnRegisterNotification(m_Data, DataChanged);
|
|
m_Data = null;
|
|
}
|
|
|
|
base.OnDisable();
|
|
}
|
|
|
|
private void UnregisterAnchors()
|
|
{
|
|
foreach (var anchor in flowInputAnchors)
|
|
viewController.UnregisterFlowAnchorController(anchor);
|
|
foreach (var anchor in flowOutputAnchors)
|
|
viewController.UnregisterFlowAnchorController(anchor);
|
|
}
|
|
|
|
protected void DataChanged()
|
|
{
|
|
NotifyChange(AnyThing);
|
|
}
|
|
|
|
protected override VFXDataAnchorController AddDataAnchor(VFXSlot slot, bool input, bool hidden)
|
|
{
|
|
if (input)
|
|
{
|
|
VFXContextDataInputAnchorController anchorController = new VFXContextDataInputAnchorController(slot, this, hidden);
|
|
|
|
return anchorController;
|
|
}
|
|
else
|
|
{
|
|
VFXContextDataOutputAnchorController anchorController = new VFXContextDataOutputAnchorController(slot, this, hidden);
|
|
|
|
return anchorController;
|
|
}
|
|
}
|
|
|
|
VFXData m_Data = null;
|
|
|
|
protected override void ModelChanged(UnityEngine.Object obj)
|
|
{
|
|
SyncFlowAnchors();
|
|
SyncControllers();
|
|
// make sure we listen to the right data
|
|
|
|
if (!object.ReferenceEquals(m_Data, null) && model.GetData() != m_Data)
|
|
{
|
|
viewController.UnRegisterNotification(m_Data, DataChanged);
|
|
m_Data = null;
|
|
}
|
|
if (m_Data == null && model.GetData() != null)
|
|
{
|
|
m_Data = model.GetData();
|
|
|
|
viewController.RegisterNotification(m_Data, DataChanged);
|
|
}
|
|
|
|
viewController.FlowEdgesMightHaveChanged();
|
|
|
|
base.ModelChanged(obj);
|
|
}
|
|
|
|
public VFXContextController(VFXContext model, VFXViewController viewController) : base(model, viewController)
|
|
{
|
|
UnregisterAnchors();
|
|
SyncControllers();
|
|
|
|
if (model is VFXSubgraphContext)
|
|
{
|
|
// Prevent breaking the editor opening.
|
|
try
|
|
{
|
|
SyncFlowAnchors();
|
|
model.ResyncSlots(true);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogException(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SyncFlowAnchors()
|
|
{
|
|
if (this.model.inputType != VFXDataType.None)
|
|
{
|
|
for (int slot = m_FlowInputAnchors.Count; slot < this.model.inputFlowSlot.Length; ++slot)
|
|
{
|
|
var inAnchor = new VFXFlowInputAnchorController();
|
|
inAnchor.Init(this, slot);
|
|
m_FlowInputAnchors.Add(inAnchor);
|
|
viewController.RegisterFlowAnchorController(inAnchor);
|
|
}
|
|
while (this.model.inputFlowSlot.Length < m_FlowInputAnchors.Count)
|
|
{
|
|
var removedAnchor = m_FlowInputAnchors[m_FlowInputAnchors.Count - 1];
|
|
removedAnchor.OnDisable();
|
|
viewController.UnregisterFlowAnchorController(removedAnchor);
|
|
|
|
m_FlowInputAnchors.RemoveAt(m_FlowInputAnchors.Count - 1);
|
|
}
|
|
}
|
|
|
|
if (this.model.outputType != VFXDataType.None)
|
|
{
|
|
for (int slot = m_FlowOutputAnchors.Count; slot < this.model.outputFlowSlot.Length; ++slot)
|
|
{
|
|
var outAnchor = new VFXFlowOutputAnchorController();
|
|
outAnchor.Init(this, slot);
|
|
m_FlowOutputAnchors.Add(outAnchor);
|
|
viewController.RegisterFlowAnchorController(outAnchor);
|
|
}
|
|
while (this.model.outputFlowSlot.Length < m_FlowOutputAnchors.Count)
|
|
{
|
|
var removedAnchor = m_FlowOutputAnchors[m_FlowOutputAnchors.Count - 1];
|
|
removedAnchor.OnDisable();
|
|
viewController.UnregisterFlowAnchorController(removedAnchor);
|
|
|
|
m_FlowOutputAnchors.RemoveAt(m_FlowOutputAnchors.Count - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddBlock(int index, VFXBlock block, bool initSpace = false)
|
|
{
|
|
if (initSpace)
|
|
{
|
|
if (model.spaceable && block.inputSlots.Any(o => o.spaceable))
|
|
{
|
|
var contextSpace = model.space;
|
|
foreach (var inputSlot in block.inputSlots.Where(o => o.spaceable))
|
|
{
|
|
inputSlot.space = contextSpace;
|
|
}
|
|
}
|
|
}
|
|
model.AddChild(block, index);
|
|
}
|
|
|
|
public void ReorderBlock(int index, VFXBlock block)
|
|
{
|
|
if (block.GetParent() == base.model && model.GetIndex(block) < index)
|
|
{
|
|
--index;
|
|
}
|
|
|
|
if (index < 0 || index >= base.model.GetNbChildren())
|
|
index = -1;
|
|
|
|
model.AddChild(block, index);
|
|
}
|
|
|
|
public void RemoveBlock(VFXBlock block)
|
|
{
|
|
model.RemoveChild(block);
|
|
VFXModel.UnlinkModel(block);
|
|
}
|
|
|
|
public int FindBlockIndexOf(VFXBlockController controller)
|
|
{
|
|
return m_BlockControllers.IndexOf(controller);
|
|
}
|
|
|
|
private void SyncControllers()
|
|
{
|
|
var m_NewControllers = new List<VFXBlockController>();
|
|
foreach (var block in model.children)
|
|
{
|
|
var newController = m_BlockControllers.Find(p => p.model == block);
|
|
if (newController == null) // If the controller does not exist for this model, create it
|
|
{
|
|
newController = new VFXBlockController(block, this);
|
|
newController.ForceUpdate();
|
|
}
|
|
m_NewControllers.Add(newController);
|
|
}
|
|
|
|
foreach (var deletedController in m_BlockControllers.Except(m_NewControllers))
|
|
{
|
|
deletedController.OnDisable();
|
|
}
|
|
m_BlockControllers = m_NewControllers;
|
|
}
|
|
|
|
static VFXBlock DuplicateBlock(VFXBlock block)
|
|
{
|
|
var dependencies = new HashSet<ScriptableObject>();
|
|
dependencies.Add(block);
|
|
block.CollectDependencies(dependencies);
|
|
|
|
var duplicated = VFXMemorySerializer.DuplicateObjects(dependencies.ToArray());
|
|
|
|
VFXBlock result = duplicated.OfType<VFXBlock>().First();
|
|
|
|
block.activationSlot.UnlinkAll(true, false);
|
|
foreach (var slot in result.inputSlots)
|
|
{
|
|
slot.UnlinkAll(true, false);
|
|
}
|
|
foreach (var slot in result.outputSlots)
|
|
{
|
|
slot.UnlinkAll(true, false);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal void BlocksDropped(int blockIndex, IEnumerable<VFXBlockController> draggedBlocks, bool copy)
|
|
{
|
|
//Sort draggedBlock in the order we want them to appear and not the selected order ( blocks in the same context should appear in the same order as they where relative to each other).
|
|
draggedBlocks = draggedBlocks.OrderBy(t => t.index).GroupBy(t => t.contextController).SelectMany<IGrouping<VFXContextController, VFXBlockController>, VFXBlockController>(t => t.Select(u => u));
|
|
|
|
if (copy)
|
|
{
|
|
var copiedBlocks = VFXCopy.CopyBlocks(draggedBlocks);
|
|
VFXPaste.PasteBlocks(viewController, copiedBlocks, model, blockIndex);
|
|
}
|
|
else
|
|
{
|
|
foreach (VFXBlockController draggedBlock in draggedBlocks)
|
|
{
|
|
this.ReorderBlock(blockIndex++, draggedBlock.model);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override IEnumerable<Controller> allChildren
|
|
{
|
|
get { return m_BlockControllers.Cast<Controller>(); }
|
|
}
|
|
|
|
public static bool IsTypeExpandable(System.Type type)
|
|
{
|
|
return !type.IsPrimitive &&
|
|
!typeof(UnityObject).IsAssignableFrom(type) &&
|
|
type != typeof(AnimationCurve) &&
|
|
!type.IsEnum &&
|
|
type != typeof(Gradient) &&
|
|
type != typeof(CameraBuffer) &&
|
|
type != typeof(Matrix4x4) &&
|
|
type != typeof(GPUEvent);
|
|
}
|
|
}
|
|
}
|