public override void OnClick(Node source, Vector2 mousePosition) { var type = source.ReturnType(); if (type.IsSubclassOf(typeof(System.MulticastDelegate))) { NodeEditorUtility.AddNewNode(graph.editorData, null, null, mousePositionOnCanvas, delegate(EventHook n) { n.target = new MemberData(source, MemberData.TargetType.ValueNode); }); } else { NodeEditorUtility.AddNewNode(graph.editorData, null, null, mousePositionOnCanvas, delegate(NodeSetValue n) { n.target = new MemberData(source, MemberData.TargetType.ValueNode); if (type.IsSubclassOf(typeof(System.MulticastDelegate))) { NodeEditorUtility.AddNewNode(graph.editorData, null, null, mousePositionOnCanvas, delegate(NodeLambda node) { n.value = new MemberData(node, MemberData.TargetType.ValueNode); n.setType = SetType.Add; node.delegateType = MemberData.CreateFromType(type); }); } else if (ReflectionUtils.CanCreateInstance(type)) { n.value = new MemberData(ReflectionUtils.CreateInstance(type), MemberData.TargetType.Values); } }); } graph.Refresh(); }
public override void OnClick(Node source, PortCommandData data, Vector2 mousePosition) { if (source.owner) { Undo.SetCurrentGroupName("Promote to node"); Undo.RegisterFullObjectHierarchyUndo(source.owner, "Promote to node"); } MemberData m = data.member; if (data.portType != null && (!m.isAssigned || m.type == null)) { if (ReflectionUtils.CanCreateInstance(data.portType)) { m.CopyFrom(new MemberData(ReflectionUtils.CreateInstance(data.portType))); } else { m.CopyFrom(MemberData.CreateFromValue(null, data.portType)); } } NodeEditorUtility.AddNewNode <MultipurposeNode>(graph.editorData, null, null, new Vector2(source.editorRect.x - 100, source.editorRect.y), (node) => { node.target.target = new MemberData(m); MemberDataUtility.UpdateMultipurposeMember(node.target); m.CopyFrom(new MemberData(node, MemberData.TargetType.ValueNode)); }); graph.Refresh(); }
protected override void InitializeView() { base.InitializeView(); Nodes.MakeArrayNode node = targetNode as Nodes.MakeArrayNode; if (node.elementType.isAssigned) { System.Type type = node.elementType.Get <System.Type>(); FilterAttribute filter = new FilterAttribute(type); for (int i = 0; i < node.values.Count; i++) { int x = i; AddInputValuePort( new PortData() { portID = "Element#" + x, onValueChanged = (o) => { RegisterUndo(); node.values[x] = o as MemberData; }, getPortName = () => "Element " + x, getPortType = () => filter.GetActualType(), getPortValue = () => node.values[x], filter = filter, } ); } } ControlView control = new ControlView(); control.Add(new Button(() => { if (node.values.Count > 0) { RegisterUndo(); node.values.RemoveAt(node.values.Count - 1); MarkRepaint(); } }) { text = "-" }); control.Add(new Button(() => { RegisterUndo(); MemberData val; if (ReflectionUtils.CanCreateInstance(node.elementType.Get <Type>())) { val = new MemberData(ReflectionUtils.CreateInstance(node.elementType.Get <Type>())); } else { val = MemberData.empty; } node.values.Add(val); MarkRepaint(); }) { text = "+" }); AddControl(Direction.Input, control); }
public override void CheckError() { base.CheckError(); uNodeUtility.CheckError(target, this, "target"); uNodeUtility.CheckError(value, this, "value"); if (target.isAssigned && value.isAssigned && target.type != null) { try { bool isDelegate = target.type.IsSubclassOf(typeof(Delegate)); if (isDelegate) { if (setType != SetType.Add && setType != SetType.Subtract) { if (target.targetType == MemberData.TargetType.Event) { RegisterEditorError("Event can only be Add or Remove"); } else if (target.targetType == MemberData.TargetType.ValueNode && target.instance is MultipurposeNode) { var node = target.instance as MultipurposeNode; if (node.target.target.targetType == MemberData.TargetType.Event) { RegisterEditorError("Event can only be Add or Remove"); } } } } else if (value.type != null) { if (setType == SetType.Change) { if (!value.type.IsCastableTo(typeof(uNodeRoot)) && !value.type.IsCastableTo(target.type) && !target.type.IsCastableTo(value.type) && value.type != typeof(object)) { RegisterEditorError(value.type.PrettyName(true) + " can't be set to " + target.type.PrettyName(true)); } } else if (ReflectionUtils.CanCreateInstance(target.type) && ReflectionUtils.CanCreateInstance(value.type)) { uNodeHelper.SetObject( ReflectionUtils.CreateInstance(target.type), ReflectionUtils.CreateInstance(value.type), setType); } } } catch (System.Exception ex) { RegisterEditorError(ex.Message); } } }
public static Events.Action onAddCompareAction(MemberData member) { CompareOperator action = new CompareOperator(); action.targetA = member; if (member.type != null && ReflectionUtils.CanCreateInstance(member.type)) { action.targetB = new MemberData(ReflectionUtils.CreateInstance(member.type)); } else { action.targetB = new MemberData(null, MemberData.TargetType.Values); } return(action); }
public static Events.Action onAddSetAction(MemberData member) { SetValue action = new SetValue(); action.target = member; if (member.type != null && ReflectionUtils.CanCreateInstance(member.type)) { action.value = new MemberData(ReflectionUtils.CreateInstance(member.type)); } else { action.value = new MemberData(null, MemberData.TargetType.Values); } return(action); }
public override bool IsValidPort(Node source, PortCommandData data) { var member = data.member; if (member == null) { return(false); } else if (filter != null && filter.Types != null && filter.Types.Count > 0) { Type t = filter.GetActualType(); if (ReflectionUtils.CanCreateInstance(t) && !t.IsPrimitive && t != typeof(string)) { return(true); } } return(false); }
public static Condition onAddEqualityComparer(MemberData member) { EqualityCompare cond = new EqualityCompare(); cond.target = new MultipurposeMember() { target = member }; MemberDataUtility.UpdateMultipurposeMember(cond.target); if (member.type != null && ReflectionUtils.CanCreateInstance(member.type)) { cond.value = new MemberData(ReflectionUtils.CreateInstance(member.type)); } else { cond.value = new MemberData(null, MemberData.TargetType.Values); } return(cond); }
public static List <FieldDecorator> FindDecorators() { if (_fieldDecorators == null) { _fieldDecorators = new List <FieldDecorator>(); foreach (var assembly in EditorReflectionUtility.GetAssemblies()) { try { foreach (System.Type type in EditorReflectionUtility.GetAssemblyTypes(assembly)) { if (type.IsSubclassOf(typeof(FieldDecorator)) && ReflectionUtils.CanCreateInstance(type)) { var control = ReflectionUtils.CreateInstance(type) as FieldDecorator; _fieldDecorators.Add(control); } } } catch { continue; } } _fieldDecorators.Sort((x, y) => CompareUtility.Compare(x.order, y.order)); } return(_fieldDecorators); }
public bool IsValidTypeForValue(Type t) { if (t == null) { return(true); } if (t.IsByRef) { t = t.GetElementType(); } if (t.IsInterface || t.IsAbstract) { return(false); } if (!t.IsValueType && !t.IsInterface && t != typeof(string)) { return(false); } if (!DisplayValueType && t.IsValueType) { return(false); } if (!DisplayRuntimeType && t is uNode.RuntimeType) { return(false); } if (!ReflectionUtils.CanCreateInstance(t)) { return(false); } if (HideTypes != null && HideTypes.Count > 0) { for (int i = 0; i < HideTypes.Count; i++) { Type type = HideTypes[i]; if (type == null) { continue; } if (type.IsByRef) { type = type.GetElementType(); } if (type == t || (HideSubClassType && t.IsSubclassOf(type))) { return(false); } } } if (attributeTargets != AttributeTargets.All && t.IsCastableTo(typeof(System.Attribute))) { if (t.IsDefined(typeof(AttributeUsageAttribute), true)) { var a = t.GetCustomAttributes(typeof(AttributeUsageAttribute), true)[0] as AttributeUsageAttribute; if (!a.ValidOn.HasFlags(attributeTargets)) { return(false); } } } if (t == typeof(void) && !VoidType) { return(false); } if (Types == null || Types.Count == 0) { return(true); } bool hasType = false; for (int i = 0; i < Types.Count; i++) { Type type = Types[i]; if (type == null) { continue; } if (type.IsByRef) { type = type.GetElementType(); } if (t.IsCastableTo(type)) { hasType = true; break; } if (SelectBaseType && t.IsAssignableFrom(type)) { hasType = true; break; } } return(hasType); }
public static void ShowAddEventMenu( Vector2 position, Object instance, Action <Block> addConditionEvent = null) { List <ItemSelector.CustomItem> customItems = new List <ItemSelector.CustomItem>(); var conditions = GetConditionMenus(); foreach (var c in conditions) { var type = c.type; customItems.Add(new ItemSelector.CustomItem(c.name, delegate() { if (addConditionEvent != null) { Block act; if (type.IsSubclassOf(typeof(Block))) { act = ReflectionUtils.CreateInstance(type) as Block; } else if (type.IsCastableTo(typeof(IDataNode <bool>))) { act = new HLCondition() { type = MemberData.CreateFromType(type) }; } else { throw new Exception("The type must inherith from Block or IDataNode<bool>"); } addConditionEvent(act); } }, c.category)); } ItemSelector.SortCustomItems(customItems); FilterAttribute filter = new FilterAttribute() { InvalidTargetType = MemberData.TargetType.Values | MemberData.TargetType.Null, MaxMethodParam = int.MaxValue, Instance = true, VoidType = false, }; ItemSelector w = ItemSelector.ShowWindow(instance, filter, (member) => { if (instance != null && !member.isStatic) { Type startType = member.startType; if (startType != null && member.instance == null) { if (instance.GetType().IsCastableTo(startType)) { member.instance = instance; } else if (member.IsTargetingUNode) { if (member.instance == null) { member.instance = instance; } } else if (instance is Component) { if (startType == typeof(GameObject)) { member.instance = (instance as Component).gameObject; } else if (startType.IsSubclassOf(typeof(Component))) { member.instance = (instance as Component).GetComponent(startType); } } else if (instance is GameObject) { if (startType == typeof(GameObject)) { member.instance = instance as GameObject; } else if (startType.IsSubclassOf(typeof(Component))) { member.instance = (instance as GameObject).GetComponent(startType); } } if (member.instance == null && ReflectionUtils.CanCreateInstance(startType)) { member.instance = ReflectionUtils.CreateInstance(startType); } } if (member.instance == null) { member.instance = MemberData.none; } } Condition condition = null; System.Action addCondition = () => { if (addConditionEvent != null) { addConditionEvent(condition); } }; switch (member.targetType) { case MemberData.TargetType.Constructor: case MemberData.TargetType.Method: { GenericMenu menu = new GenericMenu(); if (member.type == typeof(bool)) { menu.AddItem(new GUIContent("Compare Return Value"), false, () => { condition = onAddCompareValue(member); addCondition(); }); } menu.AddItem(new GUIContent("Equality Compare"), false, () => { condition = onAddEqualityComparer(member); addCondition(); }); menu.AddItem(new GUIContent("Is Compare"), false, () => { condition = onAddIsComparer(member); addCondition(); }); menu.ShowAsContext(); break; } case MemberData.TargetType.Field: case MemberData.TargetType.Property: case MemberData.TargetType.uNodeVariable: case MemberData.TargetType.uNodeProperty: case MemberData.TargetType.uNodeLocalVariable: case MemberData.TargetType.uNodeGroupVariable: { GenericMenu menu = new GenericMenu(); if (member.type == typeof(bool)) { menu.AddItem(new GUIContent("Compare Return Value"), false, () => { condition = onAddCompareValue(member); addCondition(); }); } menu.AddItem(new GUIContent("Equality Compare"), false, () => { condition = onAddEqualityComparer(member); addCondition(); }); menu.AddItem(new GUIContent("Is Compare"), false, () => { condition = onAddIsComparer(member); addCondition(); }); menu.ShowAsContext(); break; } default: condition = onAddCompareValue(member); addCondition(); break; } }, false, customItems).ChangePosition(position); w.displayNoneOption = false; w.displayCustomVariable = false; w.customItems = customItems; }
public static void ShowAddActionMenu(Vector2 position, Action <Events.Action> action, UnityEngine.Object instance, bool acceptCoroutine = false) { List <ItemSelector.CustomItem> customItems = new List <ItemSelector.CustomItem>(); var actions = GetActionMenus(acceptCoroutine); foreach (var a in actions) { var type = a.type; customItems.Add(new ItemSelector.CustomItem(a.name, delegate() { Events.Action act; if (type.IsSubclassOf(typeof(Events.Action))) { act = ReflectionUtils.CreateInstance(type) as Events.Action; } else { act = new HLAction() { type = MemberData.CreateFromType(type) }; } action(act); }, a.category)); } ItemSelector.SortCustomItems(customItems); FilterAttribute filter = new FilterAttribute() { InvalidTargetType = MemberData.TargetType.Values | MemberData.TargetType.Null | //MemberData.TargetType.Constructor | MemberData.TargetType.SelfTarget, MaxMethodParam = int.MaxValue, Instance = true, VoidType = true }; ItemSelector w = ItemSelector.ShowWindow(instance, filter, (member) => { if (!(member.instance is UnityEngine.Object) && instance != null && !member.isStatic) { Type startType = member.startType; if (startType != null && member.instance == null) { if (instance.GetType().IsCastableTo(startType)) { member.instance = instance; } else if (member.IsTargetingUNode) { if (member.instance == null) { member.instance = instance; } } else if (instance is Component) { if (startType == typeof(GameObject)) { member.instance = (instance as Component).gameObject; } else if (startType.IsSubclassOf(typeof(Component))) { member.instance = (instance as Component).GetComponent(startType); } } else if (instance is GameObject) { if (startType == typeof(GameObject)) { member.instance = instance as GameObject; } else if (startType.IsSubclassOf(typeof(Component))) { member.instance = (instance as GameObject).GetComponent(startType); } } if (member.instance == null && ReflectionUtils.CanCreateInstance(startType)) { member.instance = ReflectionUtils.CreateInstance(startType); } } if (member.instance == null) { member.instance = MemberData.none; } } switch (member.targetType) { case MemberData.TargetType.uNodeFunction: case MemberData.TargetType.Constructor: case MemberData.TargetType.Method: { if (member.type != typeof(void)) { GenericMenu menu = new GenericMenu(); menu.AddItem(new GUIContent("Invoke"), false, () => { action(onAddGetAction(member)); }); menu.AddItem(new GUIContent("Compare"), false, () => { action(onAddCompareAction(member)); }); menu.ShowAsContext(); } else { action(onAddGetAction(member)); } break; } case MemberData.TargetType.Field: case MemberData.TargetType.Property: case MemberData.TargetType.uNodeProperty: case MemberData.TargetType.uNodeVariable: case MemberData.TargetType.uNodeLocalVariable: case MemberData.TargetType.uNodeGroupVariable: case MemberData.TargetType.uNodeParameter: { GenericMenu menu = new GenericMenu(); var members = member.GetMembers(); if (members == null || members[members.Length - 1] == null || ReflectionUtils.CanGetMember(members[members.Length - 1])) { menu.AddItem(new GUIContent("Get"), false, () => { action(onAddGetAction(member)); }); } if (members == null || members[members.Length - 1] == null || ReflectionUtils.CanSetMember(members[members.Length - 1])) { menu.AddItem(new GUIContent("Set"), false, () => { action(onAddSetAction(member)); }); } menu.AddItem(new GUIContent("Compare"), false, () => { action(onAddCompareAction(member)); }); menu.ShowAsContext(); break; } default: throw new Exception("Unsupported target kind:" + member.targetType); } }, false, customItems).ChangePosition(position); w.displayNoneOption = false; w.displayCustomVariable = false; w.customItems = customItems; }
public override void OnInspectorGUI() { MultiArithmeticNode node = target as MultiArithmeticNode; DrawDefaultInspector(); VariableEditorUtility.DrawMembers(new GUIContent("Targets"), node.targets, node, new FilterAttribute(typeof(object)), (obj) => { node.targets = obj; }, () => { uNodeEditorUtility.RegisterUndo(node); var type = node.ReturnType(); if (type != typeof(object) && ReflectionUtils.CanCreateInstance(type)) { node.targets.Add(new MemberData(ReflectionUtils.CreateInstance(type))); } else if (node.targets.Count > 0) { node.targets.Add(new MemberData(node.targets[node.targets.Count - 1])); } else { node.targets.Add(new MemberData()); } }); if (GUILayout.Button(new GUIContent("Change Operator"))) { var customItems = new List <ItemSelector.CustomItem>(); { //Primitives customItems.AddRange(GetCustomItemForPrimitives(node, typeof(int))); customItems.AddRange(GetCustomItemForPrimitives(node, typeof(float))); } var ns = NodeGraph.GetOpenedGraphUsingNamespaces(); var preference = uNodePreference.GetPreference(); var assemblies = EditorReflectionUtility.GetAssemblies(); var includedAssemblies = uNodePreference.GetIncludedAssemblies(); foreach (var assembly in assemblies) { if (!includedAssemblies.Contains(assembly.GetName().Name)) { continue; } var operators = EditorReflectionUtility.GetOperators(assembly, (op) => { return(ns == null || ns.Contains(op.DeclaringType.Namespace)); }); if (operators.Count > 0) { foreach (var op in operators) { switch (op.Name) { case "op_Addition": { var parameters = op.GetParameters(); customItems.Add(GetCustomItem(node, parameters[0].ParameterType, parameters[1].ParameterType, op.DeclaringType, op.ReturnType, ArithmeticType.Add)); break; } case "op_Subtraction": { var parameters = op.GetParameters(); customItems.Add(GetCustomItem(node, parameters[0].ParameterType, parameters[1].ParameterType, op.DeclaringType, op.ReturnType, ArithmeticType.Subtract)); break; } case "op_Division": { var parameters = op.GetParameters(); customItems.Add(GetCustomItem(node, parameters[0].ParameterType, parameters[1].ParameterType, op.DeclaringType, op.ReturnType, ArithmeticType.Divide)); break; } case "op_Multiply": { var parameters = op.GetParameters(); customItems.Add(GetCustomItem(node, parameters[0].ParameterType, parameters[1].ParameterType, op.DeclaringType, op.ReturnType, ArithmeticType.Multiply)); break; } case "op_Modulus": { var parameters = op.GetParameters(); customItems.Add(GetCustomItem(node, parameters[0].ParameterType, parameters[1].ParameterType, op.DeclaringType, op.ReturnType, ArithmeticType.Modulo)); break; } } } } } customItems.Sort((x, y) => { if (x.category == y.category) { return(string.Compare(x.name, y.name)); } return(string.Compare(x.category, y.category)); }); if (customItems.Count > 0) { ItemSelector.ShowWindow(null, null, null, false, customItems). ChangePosition( GUIUtility.GUIToScreenRect(GUILayoutUtility.GetLastRect()) ).displayDefaultItem = false; } } }
private void BuildContextualMenu(ContextualMenuPopulateEvent evt) { if (config.type != null) { if (config.filter == null || !config.filter.SetMember && config.filter.IsValidTarget(MemberData.TargetType.Values)) { evt.menu.AppendAction("To Default", (e) => { if (config.type == typeof(Type)) { member = new MemberData(typeof(object)); } else if (config.type is RuntimeType) { member = MemberData.CreateFromValue(null, config.type); } else { member = new MemberData(ReflectionUtils.CanCreateInstance(config.type) ? ReflectionUtils.CreateInstance(config.type) : null) { startType = config.type, targetTypeName = config.type.FullName, }; } config.OnValueChanged(member); config.owner.OnValueChanged(); config.owner.MarkRepaint(); UpdateControl(); uNodeEditor.GUIChanged(); }, DropdownMenuAction.AlwaysEnabled); if (config.type == typeof(object)) { var types = EditorReflectionUtility.GetCommonType(); foreach (var t in types) { evt.menu.AppendAction("To Value/" + t.PrettyName(), (e) => { member = new MemberData(ReflectionUtils.CanCreateInstance(t) ? ReflectionUtils.CreateInstance(t) : null) { startType = t, targetTypeName = t.FullName, }; config.OnValueChanged(member); config.owner.OnValueChanged(); config.owner.MarkRepaint(); UpdateControl(); uNodeEditor.GUIChanged(); }, DropdownMenuAction.AlwaysEnabled); } } else if (config.type == typeof(Type)) { var mPos = NodeGraph.openedGraph.GetMousePosition(); evt.menu.AppendAction("Change Type", (e) => { TypeSelectorWindow.ShowWindow(mPos, new FilterAttribute() { OnlyGetType = true }, delegate(MemberData[] types) { uNodeEditorUtility.RegisterUndo(config.owner.targetNode); member.CopyFrom(types[0]); config.OnValueChanged(member); config.owner.OnValueChanged(); config.owner.MarkRepaint(); UpdateControl(); uNodeEditor.GUIChanged(); }, new TypeItem[1] { member }).targetObject = config.owner.targetNode; }, DropdownMenuAction.AlwaysEnabled); } if (!config.type.IsValueType) { evt.menu.AppendAction("To Null", (e) => { uNodeEditorUtility.RegisterUndo(config.owner.targetNode); member.CopyFrom(MemberData.Null); config.OnValueChanged(member); config.owner.OnValueChanged(); config.owner.MarkRepaint(); UpdateControl(); uNodeEditor.GUIChanged(); }, DropdownMenuAction.AlwaysEnabled); } } } }
void InitializeView() { if (data.block == null) { return; } if (data.block is Events.HLAction || data.block is Events.HLCondition) { InitializeHLBlock(data.block); return; } var fields = EditorReflectionUtility.GetFields(data.block.GetType()); if (fields != null && fields.Length > 0) { for (int idx = 0; idx < fields.Length; idx++) { FieldInfo field = fields[idx]; if (uNodeGUIUtility.IsHide(field, data.block)) { continue; } Type type = field.FieldType; if (type == typeof(MemberData)) { MemberData member = field.GetValueOptimized(data.block) as MemberData; object[] fieldAttribute = field.GetCustomAttributes(true); if (!ReflectionUtils.TryCorrectingAttribute(data.block, ref fieldAttribute)) { continue; } var filter = ReflectionUtils.GetAttribute <FilterAttribute>(fieldAttribute); if (member == null) { if (filter != null && !filter.SetMember && !filter.OnlyGetType && ReflectionUtils.CanCreateInstance(filter.GetActualType())) { member = new MemberData(ReflectionUtils.CreateInstance(filter.GetActualType())); } else if (filter != null && !filter.SetMember && !filter.OnlyGetType) { member = MemberData.none; } field.SetValueOptimized(data.block, member); Repaint(); } bool hasDependencies = EditorReflectionUtility.HasFieldDependencies(new string[] { field.Name }, fields); var port = AddPort(new PortData() { getPortName = () => ObjectNames.NicifyVariableName(field.Name), getPortType = () => filter?.GetActualType() ?? typeof(object), getPortValue = () => field.GetValueOptimized(data.block), filter = filter, onValueChanged = (obj) => { RegisterUndo(); member = obj as MemberData; field.SetValueOptimized(data.block, member); Repaint(); if (hasDependencies) { owner.nodeView.MarkRepaint(); } }, }); port.Add(new ControlView(port.portData.InstantiateControl(true), true)); } else if (type == typeof(MultipurposeMember)) { InitMultipurposeMember(field); } else { object fieldVal = field.GetValueOptimized(data.block); object[] fieldAttribute = field.GetCustomAttributes(true); if (!ReflectionUtils.TryCorrectingAttribute(data.block, ref fieldAttribute)) { continue; } bool hasDependencies = EditorReflectionUtility.HasFieldDependencies(new string[] { field.Name }, fields); var filter = ReflectionUtils.GetAttribute <FilterAttribute>(fieldAttribute); ControlConfig config = new ControlConfig() { owner = owner.nodeView, value = fieldVal, type = type, filter = filter, onValueChanged = (obj) => { RegisterUndo(); field.SetValueOptimized(data.block, obj); Repaint(); if (hasDependencies) { owner.nodeView.MarkRepaint(); } }, }; var valueControl = UIElementUtility.CreateControl(type, config, true); AddControl(field.Name, new ControlView(valueControl, true)); if (fieldVal is IList <MemberData> ) { IList <MemberData> members = fieldVal as IList <MemberData>; if (members != null) { for (int i = 0; i < members.Count; i++) { int index = i; var member = members[i]; if (member == null) { if (filter != null && !filter.SetMember && !filter.OnlyGetType && ReflectionUtils.CanCreateInstance(filter.GetActualType())) { member = new MemberData(ReflectionUtils.CreateInstance(filter.GetActualType())); } else { member = MemberData.none; } members[index] = member; field.SetValueOptimized(data.block, members); Repaint(); } var port = AddPort(new PortData() { getPortName = () => "Element " + index.ToString(), getPortType = () => filter?.GetActualType() ?? typeof(object), getPortValue = () => (field.GetValueOptimized(data.block) as IList <MemberData>)[index], filter = filter, onValueChanged = (obj) => { RegisterUndo(); member = obj as MemberData; members[index] = member; field.SetValueOptimized(data.block, members); Repaint(); }, }); port.Add(new ControlView(port.portData.InstantiateControl(true), true)); } } } else if (fieldVal is IList) { IList list = fieldVal as IList; if (list != null) { for (int i = 0; i < list.Count; i++) { int index = i; var element = list[i]; ControlConfig cfg = new ControlConfig() { owner = owner.nodeView, value = fieldVal, type = type, filter = filter, onValueChanged = (obj) => { RegisterUndo(); field.SetValueOptimized(data.block, obj); Repaint(); }, }; var elementControl = UIElementUtility.CreateControl(type, cfg, true); AddControl("Element " + index, new ControlView(elementControl, true)); } } } } } } }