forked from BilalY/Rasagar
809 lines
25 KiB
C#
809 lines
25 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using System.Collections.ObjectModel;
|
|
using UnityEditor.VFX.UI;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace UnityEditor.VFX
|
|
{
|
|
enum VFXValueFilter
|
|
{
|
|
Default,
|
|
Range,
|
|
Enum
|
|
}
|
|
|
|
[ExcludeFromPreset]
|
|
class VFXParameter : VFXSlotContainerModel<VFXModel, VFXModel>
|
|
{
|
|
protected VFXParameter()
|
|
{
|
|
m_ExposedName = "exposedName";
|
|
m_Exposed = false;
|
|
m_UICollapsed = false;
|
|
}
|
|
|
|
public static VFXParameter Duplicate(string copyName, VFXParameter source)
|
|
{
|
|
var newVfxParameter = (VFXParameter)ScriptableObject.CreateInstance(source.GetType());
|
|
|
|
newVfxParameter.m_ExposedName = copyName;
|
|
newVfxParameter.m_Exposed = source.m_Exposed;
|
|
newVfxParameter.m_UICollapsed = source.m_UICollapsed;
|
|
newVfxParameter.m_Order = source.m_Order + 1;
|
|
newVfxParameter.m_Category = source.m_Category;
|
|
newVfxParameter.m_Min = source.m_Min;
|
|
newVfxParameter.m_Max = source.m_Max;
|
|
newVfxParameter.m_IsOutput = source.m_IsOutput;
|
|
newVfxParameter.m_EnumValues = source.m_EnumValues?.ToList();
|
|
newVfxParameter.m_Tooltip = source.m_Tooltip;
|
|
newVfxParameter.m_ValueFilter = source.m_ValueFilter;
|
|
newVfxParameter.subgraphMode = source.subgraphMode;
|
|
newVfxParameter.m_ValueExpr = source.m_ValueExpr;
|
|
newVfxParameter.Init(source.type);
|
|
|
|
if (!source.isOutput)
|
|
{
|
|
newVfxParameter.value = source.value;
|
|
}
|
|
|
|
return newVfxParameter;
|
|
}
|
|
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.None), SerializeField, FormerlySerializedAs("m_exposedName")]
|
|
private string m_ExposedName;
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.InInspector), SerializeField, FormerlySerializedAs("m_exposed")]
|
|
private bool m_Exposed;
|
|
[SerializeField]
|
|
private int m_Order;
|
|
[SerializeField]
|
|
private string m_Category;
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.None), SerializeField]
|
|
protected VFXSerializableObject m_Min;
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.None), SerializeField]
|
|
protected VFXSerializableObject m_Max;
|
|
|
|
[SerializeField]
|
|
private bool m_IsOutput;
|
|
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.None), SerializeField]
|
|
protected List<string> m_EnumValues;
|
|
|
|
public List<string> enumValues
|
|
{
|
|
get { return m_EnumValues; }
|
|
set
|
|
{
|
|
m_EnumValues = value;
|
|
Invalidate(InvalidationCause.kSettingChanged);
|
|
}
|
|
}
|
|
|
|
public object min
|
|
{
|
|
get { if (m_Min != null) return m_Min.Get(); else return null; }
|
|
|
|
set
|
|
{
|
|
var invalidateCause = InvalidationCause.kParamChanged;
|
|
|
|
if (m_Min == null || m_Min.type != type)
|
|
{
|
|
m_Min = new VFXSerializableObject(type, value);
|
|
invalidateCause = InvalidationCause.kSettingChanged;
|
|
}
|
|
else
|
|
m_Min.Set(value);
|
|
|
|
Invalidate(invalidateCause);
|
|
}
|
|
}
|
|
public object max
|
|
{
|
|
get { if (m_Max != null) return m_Max.Get(); else return null; }
|
|
|
|
set
|
|
{
|
|
var invalidateCause = InvalidationCause.kParamChanged;
|
|
|
|
if (m_Max == null || m_Max.type != type)
|
|
{
|
|
m_Max = new VFXSerializableObject(type, value);
|
|
invalidateCause = InvalidationCause.kSettingChanged;
|
|
}
|
|
else
|
|
m_Max.Set(value);
|
|
|
|
Invalidate(invalidateCause);
|
|
}
|
|
}
|
|
|
|
[SerializeField]
|
|
VFXValueFilter m_ValueFilter;
|
|
|
|
|
|
public VFXValueFilter valueFilter
|
|
{
|
|
get => m_ValueFilter;
|
|
|
|
set
|
|
{
|
|
if (value != m_ValueFilter)
|
|
{
|
|
m_ValueFilter = value;
|
|
switch (m_ValueFilter)
|
|
{
|
|
case VFXValueFilter.Default:
|
|
m_Max = m_Min = null;
|
|
m_EnumValues = null;
|
|
break;
|
|
case VFXValueFilter.Range:
|
|
m_Min = new VFXSerializableObject(type, this.value);
|
|
m_Max = new VFXSerializableObject(type, this.value);
|
|
m_EnumValues = null;
|
|
break;
|
|
case VFXValueFilter.Enum:
|
|
m_EnumValues = new List<string>();
|
|
m_EnumValues.Add("Zero");
|
|
m_EnumValues.Add("One");
|
|
m_Max = m_Min = null;
|
|
break;
|
|
}
|
|
|
|
Invalidate(InvalidationCause.kSettingChanged);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override IEnumerable<string> filteredOutSettings
|
|
{
|
|
get
|
|
{
|
|
return m_IsOutput ? Enumerable.Repeat("m_Exposed", 1) : Enumerable.Empty<string>();
|
|
}
|
|
}
|
|
|
|
|
|
public bool isOutput
|
|
{
|
|
get
|
|
{
|
|
return m_IsOutput;
|
|
}
|
|
|
|
set
|
|
{
|
|
if (m_IsOutput != value)
|
|
{
|
|
m_IsOutput = value;
|
|
|
|
if (m_IsOutput)
|
|
{
|
|
var oldSlot = outputSlots[0];
|
|
var newSlot = VFXSlot.Create(new VFXProperty(oldSlot.property.type, "i"), VFXSlot.Direction.kInput);
|
|
newSlot.value = oldSlot.value;
|
|
oldSlot.UnlinkAll(true);
|
|
ReplaceSlot(oldSlot, newSlot);
|
|
|
|
if (m_Nodes != null && m_Nodes.Count > 1)
|
|
{
|
|
m_Nodes.RemoveRange(1, m_Nodes.Count - 2);
|
|
}
|
|
m_ExprSlots = null;
|
|
m_ValueExpr = null;
|
|
m_Exposed = false;
|
|
}
|
|
else
|
|
{
|
|
var oldSlot = inputSlots[0];
|
|
var newSlot = VFXSlot.Create(new VFXProperty(oldSlot.property.type, "o"), VFXSlot.Direction.kOutput);
|
|
newSlot.value = oldSlot.value;
|
|
oldSlot.UnlinkAll(true);
|
|
ReplaceSlot(oldSlot, newSlot);
|
|
|
|
ResetOutputValueExpression();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public void ResetOutputValueExpression()
|
|
{
|
|
if (!isOutput)
|
|
{
|
|
MarkOutputExpressionsAsOutOfDate();
|
|
m_ExprSlots = outputSlots[0].GetVFXValueTypeSlots().ToArray();
|
|
m_ValueExpr = m_ExprSlots.Select(t => t.DefaultExpression(valueMode)).ToArray();
|
|
}
|
|
}
|
|
|
|
public bool canHaveValueFilter
|
|
{
|
|
get
|
|
{
|
|
return !isOutput && (type == typeof(float) || type == typeof(int) || type == typeof(uint));
|
|
}
|
|
}
|
|
|
|
[SerializeField]
|
|
string m_Tooltip;
|
|
|
|
public string tooltip
|
|
{
|
|
get
|
|
{
|
|
return m_Tooltip;
|
|
}
|
|
|
|
set
|
|
{
|
|
m_Tooltip = value;
|
|
Invalidate(InvalidationCause.kUIChanged);
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public struct NodeLinkedSlot
|
|
{
|
|
public VFXSlot outputSlot; // some slot from the parameter
|
|
public VFXSlot inputSlot;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class Node
|
|
{
|
|
public Node(int id)
|
|
{
|
|
m_Id = id;
|
|
expanded = true;
|
|
supecollapsed = false;
|
|
}
|
|
|
|
[SerializeField]
|
|
private int m_Id;
|
|
|
|
public int id => m_Id;
|
|
|
|
public List<NodeLinkedSlot> linkedSlots;
|
|
public Vector2 position;
|
|
public List<VFXSlot> expandedSlots;
|
|
public bool expanded;
|
|
public bool supecollapsed;
|
|
|
|
|
|
//Should only be called by ValidateNodes if something very wrong happened with serialization
|
|
internal void ChangeId(int newId)
|
|
{
|
|
m_Id = newId;
|
|
}
|
|
}
|
|
|
|
[SerializeField]
|
|
protected List<Node> m_Nodes;
|
|
|
|
[NonSerialized]
|
|
int m_IDCounter = 0;
|
|
|
|
public string exposedName
|
|
{
|
|
get
|
|
{
|
|
return m_ExposedName;
|
|
}
|
|
}
|
|
|
|
public bool exposed
|
|
{
|
|
get
|
|
{
|
|
return m_Exposed;
|
|
}
|
|
}
|
|
|
|
public int order
|
|
{
|
|
get { return m_Order; }
|
|
set
|
|
{
|
|
if (m_Order != value)
|
|
{
|
|
m_Order = value;
|
|
Invalidate(InvalidationCause.kUIChanged);
|
|
}
|
|
}
|
|
}
|
|
|
|
public string category
|
|
{
|
|
get { return m_Category; }
|
|
set
|
|
{
|
|
if (m_Category != value)
|
|
{
|
|
m_Category = value;
|
|
Invalidate(InvalidationCause.kUIChanged);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnModified(VFXObject obj, bool uiChange)
|
|
{
|
|
if (!isOutput && (m_ExprSlots == null || m_ValueExpr == null))
|
|
{
|
|
ResetOutputValueExpression();
|
|
}
|
|
}
|
|
|
|
public Type type
|
|
{
|
|
get
|
|
{
|
|
if (isOutput)
|
|
{
|
|
return inputSlots[0].property.type;
|
|
}
|
|
else
|
|
return outputSlots[0].property.type;
|
|
}
|
|
}
|
|
|
|
public object value
|
|
{
|
|
get
|
|
{
|
|
if (!isOutput)
|
|
return outputSlots[0].value;
|
|
return null;
|
|
}
|
|
set
|
|
{
|
|
if (isOutput)
|
|
throw new System.InvalidOperationException("output parameters have no value");
|
|
outputSlots[0].value = value;
|
|
}
|
|
}
|
|
|
|
|
|
public ReadOnlyCollection<Node> nodes
|
|
{
|
|
get
|
|
{
|
|
if (m_Nodes == null)
|
|
{
|
|
m_Nodes = new List<Node>();
|
|
}
|
|
return m_Nodes.AsReadOnly();
|
|
}
|
|
}
|
|
|
|
|
|
public Node GetNode(int id)
|
|
{
|
|
return m_Nodes.FirstOrDefault(t => t.id == id);
|
|
}
|
|
|
|
internal override void GenerateErrors(VFXErrorReporter report)
|
|
{
|
|
base.GenerateErrors(report);
|
|
|
|
var type = this.type;
|
|
if (Deprecated.s_Types.Contains(type))
|
|
{
|
|
report.RegisterError(
|
|
"DeprecatedTypeParameter",
|
|
VFXErrorType.Warning,
|
|
string.Format("The structure of the '{0}' has changed, the position property has been moved to a transform type. You should consider to recreate this parameter.", type.Name), this);
|
|
}
|
|
}
|
|
|
|
protected sealed override void OnInvalidate(VFXModel model, InvalidationCause cause)
|
|
{
|
|
base.OnInvalidate(model, cause);
|
|
|
|
if (isOutput)
|
|
return;
|
|
if (cause == InvalidationCause.kSettingChanged)
|
|
{
|
|
var valueExpr = m_ExprSlots.Select(t => t.DefaultExpression(valueMode)).ToArray();
|
|
bool valueExprChanged = true;
|
|
if (m_ValueExpr.Length == valueExpr.Length)
|
|
{
|
|
valueExprChanged = false;
|
|
for (int i = 0; i < m_ValueExpr.Length; ++i)
|
|
{
|
|
if (m_ValueExpr[i].ValueMode != valueExpr[i].ValueMode
|
|
|| m_ValueExpr[i].valueType != valueExpr[i].valueType)
|
|
{
|
|
valueExprChanged = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (valueExprChanged)
|
|
{
|
|
MarkOutputExpressionsAsOutOfDate();
|
|
m_ValueExpr = valueExpr;
|
|
outputSlots[0].InvalidateExpressionTree();
|
|
Invalidate(InvalidationCause.kExpressionGraphChanged); // As we need to update exposed list event if not connected to a compilable context
|
|
}
|
|
/* TODO : Allow VisualEffectApi to update only exposed name */
|
|
else if (exposed)
|
|
{
|
|
Invalidate(InvalidationCause.kExpressionGraphChanged);
|
|
}
|
|
}
|
|
|
|
if (cause == InvalidationCause.kParamChanged)
|
|
{
|
|
UpdateDefaultExpressionValue();
|
|
}
|
|
|
|
if (cause == InvalidationCause.kStructureChanged)
|
|
{
|
|
ResetOutputValueExpression();
|
|
}
|
|
}
|
|
|
|
protected override IEnumerable<VFXPropertyWithValue> inputProperties
|
|
{
|
|
get
|
|
{
|
|
if (isOutput)
|
|
return PropertiesFromSlotsOrDefaultFromClass(VFXSlot.Direction.kInput);
|
|
return Enumerable.Empty<VFXPropertyWithValue>();
|
|
}
|
|
}
|
|
protected override IEnumerable<VFXPropertyWithValue> outputProperties
|
|
{
|
|
get
|
|
{
|
|
if (!isOutput)
|
|
return PropertiesFromSlotsOrDefaultFromClass(VFXSlot.Direction.kOutput);
|
|
return Enumerable.Empty<VFXPropertyWithValue>();
|
|
}
|
|
}
|
|
|
|
public void Init(Type _type)
|
|
{
|
|
var slots = isOutput ? inputSlots : outputSlots;
|
|
if (_type != null && slots.Count == 0)
|
|
{
|
|
VFXSlot slot = VFXSlot.Create(new VFXProperty(_type, "o"), isOutput ? VFXSlot.Direction.kInput : VFXSlot.Direction.kOutput);
|
|
AddSlot(slot);
|
|
|
|
if (!typeof(UnityEngine.Object).IsAssignableFrom(_type) && _type != typeof(GraphicsBuffer))
|
|
slot.value = System.Activator.CreateInstance(_type);
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException("Cannot init VFXParameter");
|
|
}
|
|
|
|
ResetOutputValueExpression();
|
|
}
|
|
|
|
public override void OnEnable()
|
|
{
|
|
base.OnEnable();
|
|
|
|
onModified += OnModified;
|
|
if (!isOutput && outputSlots.Count > 0)
|
|
{
|
|
ResetOutputValueExpression();
|
|
}
|
|
|
|
if (m_Nodes != null)
|
|
{
|
|
foreach (var node in nodes)
|
|
{
|
|
if (m_IDCounter < node.id + 1)
|
|
{
|
|
m_IDCounter = node.id + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Node NewNode()
|
|
{
|
|
return new Node(m_IDCounter++);
|
|
}
|
|
|
|
public int AddNode(Vector2 pos)
|
|
{
|
|
Node info = NewNode();
|
|
|
|
info.position = pos;
|
|
|
|
if (m_Nodes == null)
|
|
{
|
|
m_Nodes = new List<Node>();
|
|
}
|
|
|
|
m_Nodes.Add(info);
|
|
|
|
Invalidate(InvalidationCause.kUIChanged);
|
|
|
|
return info.id;
|
|
}
|
|
|
|
public void RemoveNode(Node info)
|
|
{
|
|
if (m_Nodes.Contains(info))
|
|
{
|
|
if (info.linkedSlots != null)
|
|
{
|
|
foreach (var slots in info.linkedSlots)
|
|
{
|
|
slots.outputSlot.Unlink(slots.inputSlot);
|
|
}
|
|
}
|
|
m_Nodes.Remove(info);
|
|
|
|
Invalidate(InvalidationCause.kUIChanged);
|
|
}
|
|
}
|
|
|
|
public override void Sanitize(int version)
|
|
{
|
|
base.Sanitize(version);
|
|
|
|
HashSet<int> usedIds = new HashSet<int>();
|
|
|
|
if (m_Min != null && m_Min.type != null && m_ValueFilter == VFXValueFilter.Default)
|
|
m_ValueFilter = VFXValueFilter.Range;
|
|
|
|
if (m_Nodes != null)
|
|
{
|
|
foreach (var node in m_Nodes)
|
|
{
|
|
if (usedIds.Contains(node.id))
|
|
{
|
|
node.ChangeId(m_IDCounter++);
|
|
}
|
|
usedIds.Add(node.id);
|
|
}
|
|
}
|
|
}
|
|
|
|
//AddNodeRange will take ownership of the Nodes instead of copying them
|
|
public void AddNodeRange(IEnumerable<Node> infos)
|
|
{
|
|
foreach (var info in infos)
|
|
{
|
|
if (m_Nodes.Any(t => t.id == info.id))
|
|
{
|
|
info.ChangeId(m_IDCounter++);
|
|
}
|
|
m_Nodes.Add(info);
|
|
}
|
|
|
|
Invalidate(InvalidationCause.kUIChanged);
|
|
}
|
|
|
|
//SetNodes will take ownership of the Nodes instead of copying them
|
|
public void SetNodes(IEnumerable<Node> infos)
|
|
{
|
|
m_Nodes = infos.ToList();
|
|
|
|
ValidateNodes();
|
|
|
|
Invalidate(InvalidationCause.kUIChanged);
|
|
}
|
|
|
|
void GetAllLinks(List<NodeLinkedSlot> list, VFXSlot slot)
|
|
{
|
|
if (isOutput)
|
|
list.AddRange(slot.LinkedSlots.Select(t => new NodeLinkedSlot() { outputSlot = t, inputSlot = slot }));
|
|
else
|
|
list.AddRange(slot.LinkedSlots.Select(t => new NodeLinkedSlot() { outputSlot = slot, inputSlot = t }));
|
|
foreach (var child in slot.children)
|
|
{
|
|
GetAllLinks(list, child);
|
|
}
|
|
}
|
|
|
|
void GetAllExpandedSlots(List<VFXSlot> list, VFXSlot slot)
|
|
{
|
|
if (!slot.collapsed)
|
|
list.Add(slot);
|
|
foreach (var child in slot.children)
|
|
{
|
|
GetAllExpandedSlots(list, child);
|
|
}
|
|
}
|
|
|
|
public void ValidateNodes()
|
|
{
|
|
// Case of the old VFXParameter we create a new one on the same place with all the Links
|
|
if (position != Vector2.zero && nodes.Count == 0)
|
|
{
|
|
CreateDefaultNode(position);
|
|
}
|
|
else
|
|
{
|
|
// the linked slot of the outSlot decides so make sure that all appear once and only once in all the nodes
|
|
List<NodeLinkedSlot> links = new List<NodeLinkedSlot>();
|
|
|
|
var targetSlot = isOutput ? inputSlots.FirstOrDefault() : outputSlots.FirstOrDefault();
|
|
if (targetSlot == null)
|
|
return;
|
|
|
|
GetAllLinks(links, targetSlot);
|
|
HashSet<int> usedIds = new HashSet<int>();
|
|
foreach (var info in nodes)
|
|
{
|
|
// Check linkedSlots
|
|
if (info.linkedSlots == null)
|
|
{
|
|
info.linkedSlots = new List<NodeLinkedSlot>();
|
|
}
|
|
else
|
|
{
|
|
// first remove linkedSlots that are not existing
|
|
var intersect = info.linkedSlots.Intersect(links);
|
|
if (intersect.Count() != info.linkedSlots.Count())
|
|
info.linkedSlots = info.linkedSlots.Intersect(links).ToList();
|
|
}
|
|
|
|
//Check that all slots needed for
|
|
if (info.expandedSlots == null)
|
|
{
|
|
info.expandedSlots = new List<VFXSlot>();
|
|
}
|
|
else
|
|
{
|
|
if (info.expandedSlots.Any(t => t == null))
|
|
info.expandedSlots = info.expandedSlots.Where(t => t != null).ToList();
|
|
}
|
|
|
|
if (usedIds.Contains(info.id))
|
|
{
|
|
info.ChangeId(m_IDCounter++);
|
|
}
|
|
usedIds.Add(info.id);
|
|
|
|
foreach (var slot in info.linkedSlots)
|
|
{
|
|
links.Remove(slot);
|
|
}
|
|
}
|
|
// if there are some links in the output slots that are in not found in the infos, find or create a node for them.
|
|
foreach (var link in links)
|
|
{
|
|
Node newInfos = null;
|
|
if (nodes.Any())
|
|
{
|
|
//There are already some nodes, choose the closest one to restore the link
|
|
var refPosition = Vector2.zero;
|
|
object refOwner = link.inputSlot.owner;
|
|
while (refOwner is VFXModel model && refPosition == Vector2.zero)
|
|
{
|
|
refPosition = model is VFXBlock ? Vector2.zero : model.position;
|
|
refOwner = model.GetParent();
|
|
}
|
|
newInfos = nodes.OrderBy(o => (refPosition - o.position).SqrMagnitude()).First();
|
|
}
|
|
else
|
|
{
|
|
newInfos = NewNode();
|
|
m_Nodes.Add(newInfos);
|
|
}
|
|
if (newInfos.linkedSlots == null)
|
|
newInfos.linkedSlots = new List<NodeLinkedSlot>();
|
|
newInfos.linkedSlots.Add(link);
|
|
newInfos.expandedSlots = new List<VFXSlot>();
|
|
}
|
|
}
|
|
position = Vector2.zero; // Set that as a marker that the parameter has been touched by the new code.
|
|
}
|
|
|
|
public void CreateDefaultNode(Vector2 position)
|
|
{
|
|
if (m_Nodes != null && m_Nodes.Count != 0)
|
|
{
|
|
Debug.LogError("CreateDefaultNode must only be called with an empty parameter");
|
|
return;
|
|
}
|
|
var newInfos = NewNode();
|
|
newInfos.position = position;
|
|
|
|
var targetSlot = isOutput ? inputSlots[0] : outputSlots[0];
|
|
|
|
newInfos.linkedSlots = new List<NodeLinkedSlot>();
|
|
GetAllLinks(newInfos.linkedSlots, targetSlot);
|
|
newInfos.expandedSlots = new List<VFXSlot>();
|
|
GetAllExpandedSlots(newInfos.expandedSlots, targetSlot);
|
|
if (m_Nodes == null)
|
|
{
|
|
m_Nodes = new List<Node>();
|
|
}
|
|
m_Nodes.Add(newInfos);
|
|
}
|
|
|
|
public bool subgraphMode
|
|
{
|
|
get; set;
|
|
}
|
|
|
|
public void UpdateDefaultExpressionValue()
|
|
{
|
|
if (!isOutput)
|
|
{
|
|
for (int i = 0; i < m_ExprSlots.Length; ++i)
|
|
{
|
|
m_ValueExpr[i].SetContent(m_ExprSlots[i].value);
|
|
m_ExprSlots[i].Invalidate(InvalidationCause.kExpressionValueInvalidated);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void UpdateOutputExpressions()
|
|
{
|
|
if (!isOutput)
|
|
{
|
|
for (int i = 0; i < m_ExprSlots.Length; ++i)
|
|
{
|
|
m_ValueExpr[i].SetContent(m_ExprSlots[i].value);
|
|
if (!subgraphMode) // don't erase the expression in subgraph mode.
|
|
m_ExprSlots[i].SetExpression(m_ValueExpr[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void OnCopyLinksOtherSlot(VFXSlot mySlot, VFXSlot prevOtherSlot, VFXSlot newOtherSlot)
|
|
{
|
|
foreach (var node in nodes)
|
|
{
|
|
if (node.linkedSlots != null)
|
|
{
|
|
for (int i = 0; i < node.linkedSlots.Count; ++i)
|
|
{
|
|
if (node.linkedSlots[i].outputSlot == mySlot && node.linkedSlots[i].inputSlot == prevOtherSlot)
|
|
{
|
|
node.linkedSlots[i] = new NodeLinkedSlot() { outputSlot = mySlot, inputSlot = newOtherSlot };
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void OnCopyLinksMySlot(VFXSlot myPrevSlot, VFXSlot myNewSlot, VFXSlot otherSlot)
|
|
{
|
|
foreach (var node in nodes)
|
|
{
|
|
if (node.linkedSlots != null)
|
|
{
|
|
for (int i = 0; i < node.linkedSlots.Count; ++i)
|
|
{
|
|
if (node.linkedSlots[i].outputSlot == myPrevSlot && node.linkedSlots[i].inputSlot == otherSlot)
|
|
{
|
|
node.linkedSlots[i] = new NodeLinkedSlot() { outputSlot = myNewSlot, inputSlot = otherSlot };
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private VFXValue.Mode valueMode
|
|
{
|
|
get
|
|
{
|
|
return exposed ? VFXValue.Mode.Variable : VFXValue.Mode.FoldableVariable;
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
private VFXSlot[] m_ExprSlots;
|
|
|
|
[NonSerialized]
|
|
private VFXValue[] m_ValueExpr;
|
|
}
|
|
}
|