/// <summary> Returns the port that this <see cref="PortConnection"/> points to </summary> private NodePort GetPort() { if (node == null || string.IsNullOrEmpty(fieldName)) { return(null); } return(node.GetPort(fieldName)); }
/// <summary> Make a field for a serialized property. Automatically displays relevant node port. </summary> public static void PropertyField(SerializedProperty property, GUIContent label, bool includeChildren = true, params GUILayoutOption[] options) { if (property == null) { throw new NullReferenceException(); } XNode.Node node = property.serializedObject.targetObject as XNode.Node; XNode.NodePort port = node.GetPort(property.name); PropertyField(property, label, port, includeChildren); }
void Start() { port = node.GetPort(fieldName); graph = GetComponentInParent <RuntimeMathGraph>(); if (port.IsOutput && port.IsConnected) { for (int i = 0; i < port.ConnectionCount; i++) { AddConnection(); } } }
/// <summary> /// Shows all the property fields from the node /// </summary> protected virtual void ShowBodyFields() { string[] excludes = { "m_Script", "graph", "position", "ports" }; // Iterate through serialized properties and draw them like the Inspector (But with ports) SerializedProperty iterator = serializedObject.GetIterator(); bool enterChildren = true; EditorGUIUtility.labelWidth = LabelWidth; GUILayout.Space(m_PortRect.height * 0.5f); while (iterator.NextVisible(enterChildren)) { enterChildren = false; if (excludes.Contains(iterator.name)) { continue; } XNode.Node node = iterator.serializedObject.targetObject as XNode.Node; XNode.NodePort port = node.GetPort(iterator.name); // Don't allow to draw ports (// TO DO, add ports to the list now?) if (port != null) { continue; } // Save original editorStyle Color originalContentColor = GUI.contentColor; Color originalColor = EditorStyles.label.normal.textColor; Font originalFont = EditorStyles.label.font; int origianlFontSize = EditorStyles.label.fontSize; // Replace skin for entire editorStyle with custom EditorStyles.label.normal.textColor = Color.white; EditorStyles.label.font = m_NodeSkin.label.font; EditorStyles.label.fontSize = 13; // Draw property NodeEditorGUILayout.PropertyField(iterator, (NodePort)null, true); // Place original skin back to not mess other nodes EditorStyles.label.normal.textColor = originalColor; EditorStyles.label.font = originalFont; EditorStyles.label.fontSize = origianlFontSize; } }
/// <summary> /// 简单渲染 /// </summary> /// <param name="list"></param> public void SimpleDrawList(ReorderableList list) { if (chatNode == null) { chatNode = target as ChatNode; } // Debug.Log("简单渲染中"); //获取序列化后的chatslist数据 SerializedProperty arrayData = serializedObject.FindProperty(fieldName); bool hasArrayData = arrayData != null && arrayData.isArray; list.drawHeaderCallback = (Rect rect) => { string title = "对话列表"; GUI.Label(rect, title); }; list.drawElementCallback = (Rect rect, int index, bool selected, bool focused) => { #region 自定义渲染动态节点 XNode.Node node = serializedObject.targetObject as XNode.Node; XNode.NodePort port = node.GetPort(fieldName + " " + index); EditorGUI.LabelField(rect, ""); if (port != null && chatNode.chatslist[index].chatType == ChatType.option || chatNode.chatslist[index].chatType == ChatType.jump) { Vector2 pos = rect.position + (port.IsOutput ? new Vector2(rect.width + 6, 0) : new Vector2(-36, 0)); NodeEditorGUILayout.PortField(pos, port); } #endregion }; list.elementHeightCallback = (int index) => { if (chatNode.chatslist[index].chatType == ChatType.option || chatNode.chatslist[index].chatType == ChatType.jump) { SerializedProperty itemData = arrayData.GetArrayElementAtIndex(index); return(EditorGUI.GetPropertyHeight(itemData)); } else { return(0); } }; }
void Start() { if (node == null) { Destroy(this); return; } backingValuePath = fieldName; port = node.GetPort(fieldName); graph = GetComponentInParent <RuntimeGraph>(); if (port.IsOutput && port.IsConnected) { for (int i = 0; i < port.ConnectionCount; i++) { AddConnection(); } } if (port.ValueType == typeof(bool)) { transform.parent.GetComponent <Image>().color = Color.green; isBasicTypePort = true; propertyType = GUIProperty.PropertyType.Boolean; } else if (port.ValueType == typeof(string)) { transform.parent.GetComponent <Image>().color = Color.magenta; isBasicTypePort = true; propertyType = GUIProperty.PropertyType.String; } else if (port.ValueType.IsNumber()) { transform.parent.GetComponent <Image>().color = Color.yellow; isBasicTypePort = true; propertyType = GUIProperty.PropertyType.Number; } else if (port.ValueType == typeof(DummyConnection)) { transform.parent.GetComponent <Image>().color = Color.white; } else if (port.ValueType.IsEnum) { isBasicTypePort = true; transform.parent.GetComponent <Image>().color = Color.blue; propertyType = GUIProperty.PropertyType.Enumeration; } else if (port.ValueType == typeof(SceneGameObjectReference) || port.ValueType == typeof(SceneGameObject)) { transform.parent.GetComponent <Image>().color = Color.red; } else if (port.ValueType == typeof(ValueConnection)) { isBasicTypePort = true; transform.parent.GetComponent <Image>().color = Color.blue; propertyType = GUIProperty.PropertyType.String; backingValuePath = backingValuePath + "/value"; } else { transform.parent.GetComponent <Image>().color = Color.blue; } if (backingValue != null) { backingValue.gameObject.SetActive(false); } }
public void DrawList(ReorderableList list) { IList l = list.list; if (chatNode == null) { chatNode = target as ChatNode; } if (dialogueGraph == null) { dialogueGraph = window.graph as DialogueGraph; } tAsset = dialogueGraph.GetAsset(); if (tAsset != null) { foreach (var person in tAsset.persons) { //Debug.Log("角色名" + person.Name); chatNode.tPersonNameList.Add(person.Name); } } //获取序列化后的chatslist数据 SerializedProperty arrayData = serializedObject.FindProperty(fieldName); bool hasArrayData = arrayData != null && arrayData.isArray; list.drawHeaderCallback = (Rect rect) => { // Debug.Log("AAAAAAAAAAAAAAAAA"); string title = "对话列表"; GUI.Label(rect, title); }; list.drawElementCallback = (Rect rect, int index, bool selected, bool focused) => { //if (MilliSeconds() < lastBodyGUITime + 100) //{ // return; //} //lastBodyGUITime = MilliSeconds(); #region 自定义渲染动态节点 XNode.Node node = serializedObject.targetObject as XNode.Node; XNode.NodePort port = node.GetPort(fieldName + " " + index); EditorGUI.LabelField(rect, ""); if (port != null && chatNode.chatslist[index].chatType == ChatType.option || chatNode.chatslist[index].chatType == ChatType.jump) { Vector2 pos = rect.position + (port.IsOutput ? new Vector2(rect.width + 6, 0) : new Vector2(-36, 0)); NodeEditorGUILayout.PortField(pos, port); } #endregion #region 详细定义每个元素的位置 // 设置属性名宽度 //EditorGUIUtility.labelWidth = 1; Rect position = rect; position.height = EditorGUIUtility.singleLineHeight; //单个singlechatclass数据 SerializedProperty itemData = arrayData.GetArrayElementAtIndex(index); if (chatNode.chatslist[index].chatType == ChatType.cEvent || chatNode.chatslist[index].chatType == ChatType.pause) { //这里用原本的对话内容代替停止的时间 Rect typeRect = new Rect(position) { width = 130, y = position.y + 5, height = 20 }; Rect methodNameRect = new Rect(typeRect) { width = position.width - 140, x = position.x + 140, height = 20 }; SerializedProperty content_Timeproperty = itemData.FindPropertyRelative("content"); SerializedProperty typeproperty = itemData.FindPropertyRelative("chatType"); content_Timeproperty.stringValue = EditorGUI.TextArea(methodNameRect, content_Timeproperty.stringValue); SingleChatClass temp = chatNode.chatslist[index]; ChatType ty = new ChatType(); ty = (ChatType)EditorGUI.EnumPopup(typeRect, temp.chatType); typeproperty.enumValueIndex = (int)ty; } else { Rect iconRect = new Rect(position) { width = 50, height = 50 }; Rect nameTypeRect = new Rect(position) { width = position.width - 270, x = position.x + 60 }; Rect typeRect = new Rect(nameTypeRect) { width = position.width - 270, y = nameTypeRect.y + EditorGUIUtility.singleLineHeight + 7, height = 20 }; Rect contentRect = new Rect(position) { width = position.width - 140, height = 50, x = position.x + 140 }; iconProperty = itemData.FindPropertyRelative("emoji"); SerializedProperty nameProperty = itemData.FindPropertyRelative("name"); SerializedProperty contentproperty = itemData.FindPropertyRelative("content"); SerializedProperty typeproperty = itemData.FindPropertyRelative("chatType"); iconProperty.objectReferenceValue = EditorGUI.ObjectField(iconRect, iconProperty.objectReferenceValue, typeof(Sprite), false); SingleChatClass temp = chatNode.chatslist[index]; nameProperty.intValue = EditorGUI.Popup(nameTypeRect, temp.name, chatNode.tPersonNameList.ToArray()); ChatType ty = new ChatType(); ty = (ChatType)EditorGUI.EnumPopup(typeRect, temp.chatType); typeproperty.enumValueIndex = (int)ty; contentproperty.stringValue = EditorGUI.TextArea(contentRect, contentproperty.stringValue); } #endregion }; list.elementHeightCallback = (int index) => { //Debug.Log("CCCCCCCCCCCCCCCCC"); if (hasArrayData) { if (arrayData.arraySize <= index) { return(EditorGUIUtility.singleLineHeight); } SerializedProperty itemData = arrayData.GetArrayElementAtIndex(index); if (chatNode.chatslist[index].chatType == ChatType.cEvent || chatNode.chatslist[index].chatType == ChatType.pause) { return(EditorGUI.GetPropertyHeight(itemData) + 12); } return(EditorGUI.GetPropertyHeight(itemData) + 36); } else { return(EditorGUIUtility.singleLineHeight); } }; }
private static ReorderableList CreateReorderableList(string fieldName, List <XNode.NodePort> instancePorts, SerializedProperty arrayData, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.Node.ConnectionType connectionType, XNode.Node.TypeConstraint typeConstraint, Action <ReorderableList> onCreation) { bool hasArrayData = arrayData != null && arrayData.isArray; XNode.Node node = serializedObject.targetObject as XNode.Node; ReorderableList list = new ReorderableList(instancePorts, null, true, true, true, true); string label = arrayData != null ? arrayData.displayName : ObjectNames.NicifyVariableName(fieldName); list.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => { XNode.NodePort port = node.GetPort(fieldName + " " + index); if (hasArrayData) { if (arrayData.arraySize <= index) { EditorGUI.LabelField(rect, "Invalid element " + index); return; } SerializedProperty itemData = arrayData.GetArrayElementAtIndex(index); EditorGUI.PropertyField(rect, itemData, true); } else { EditorGUI.LabelField(rect, port.fieldName); } if (port != null) { Vector2 pos = rect.position + (port.IsOutput?new Vector2(rect.width + 6, 0) : new Vector2(-36, 0)); NodeEditorGUILayout.PortField(pos, port); } }; list.elementHeightCallback = (int index) => { if (hasArrayData) { if (arrayData.arraySize <= index) { return(EditorGUIUtility.singleLineHeight); } SerializedProperty itemData = arrayData.GetArrayElementAtIndex(index); return(EditorGUI.GetPropertyHeight(itemData)); } else { return(EditorGUIUtility.singleLineHeight); } }; list.drawHeaderCallback = (Rect rect) => { EditorGUI.LabelField(rect, label); }; list.onSelectCallback = (ReorderableList rl) => { reorderableListIndex = rl.index; }; list.onReorderCallback = (ReorderableList rl) => { // Move up if (rl.index > reorderableListIndex) { for (int i = reorderableListIndex; i < rl.index; ++i) { XNode.NodePort port = node.GetPort(fieldName + " " + i); XNode.NodePort nextPort = node.GetPort(fieldName + " " + (i + 1)); port.SwapConnections(nextPort); // Swap cached positions to mitigate twitching Rect rect = NodeEditorWindow.current.portConnectionPoints[port]; NodeEditorWindow.current.portConnectionPoints[port] = NodeEditorWindow.current.portConnectionPoints[nextPort]; NodeEditorWindow.current.portConnectionPoints[nextPort] = rect; } } // Move down else { for (int i = reorderableListIndex; i > rl.index; --i) { XNode.NodePort port = node.GetPort(fieldName + " " + i); XNode.NodePort nextPort = node.GetPort(fieldName + " " + (i - 1)); port.SwapConnections(nextPort); // Swap cached positions to mitigate twitching Rect rect = NodeEditorWindow.current.portConnectionPoints[port]; NodeEditorWindow.current.portConnectionPoints[port] = NodeEditorWindow.current.portConnectionPoints[nextPort]; NodeEditorWindow.current.portConnectionPoints[nextPort] = rect; } } // Apply changes serializedObject.ApplyModifiedProperties(); serializedObject.Update(); // Move array data if there is any if (hasArrayData) { arrayData.MoveArrayElement(reorderableListIndex, rl.index); } // Apply changes serializedObject.ApplyModifiedProperties(); serializedObject.Update(); NodeEditorWindow.current.Repaint(); EditorApplication.delayCall += NodeEditorWindow.current.Repaint; }; list.onAddCallback = (ReorderableList rl) => { // Add instance port postfixed with an index number string newName = fieldName + " 0"; int i = 0; while (node.HasPort(newName)) { newName = fieldName + " " + (++i); } if (io == XNode.NodePort.IO.Output) { node.AddInstanceOutput(type, connectionType, XNode.Node.TypeConstraint.None, newName); } else { node.AddInstanceInput(type, connectionType, typeConstraint, newName); } serializedObject.Update(); EditorUtility.SetDirty(node); if (hasArrayData) { arrayData.InsertArrayElementAtIndex(arrayData.arraySize); } serializedObject.ApplyModifiedProperties(); }; list.onRemoveCallback = (ReorderableList rl) => { Predicate <string> isMatchingInstancePort = x => { string[] split = x.Split(' '); if (split != null && split.Length == 2) { return(split[0] == fieldName); } else { return(false); } }; instancePorts = node.InstancePorts.Where(x => isMatchingInstancePort(x.fieldName)).OrderBy(x => x.fieldName).ToList(); int index = rl.index; // Clear the removed ports connections instancePorts[index].ClearConnections(); // Move following connections one step up to replace the missing connection for (int k = index + 1; k < instancePorts.Count(); k++) { for (int j = 0; j < instancePorts[k].ConnectionCount; j++) { XNode.NodePort other = instancePorts[k].GetConnection(j); instancePorts[k].Disconnect(other); instancePorts[k - 1].Connect(other); } } // Remove the last instance port, to avoid messing up the indexing node.RemoveInstancePort(instancePorts[instancePorts.Count() - 1].fieldName); serializedObject.Update(); EditorUtility.SetDirty(node); if (hasArrayData) { arrayData.DeleteArrayElementAtIndex(index); // Error handling. If the following happens too often, file a bug report at https://github.com/Siccity/xNode/issues if (instancePorts.Count <= arrayData.arraySize) { while (instancePorts.Count <= arrayData.arraySize) { arrayData.DeleteArrayElementAtIndex(arrayData.arraySize - 1); } UnityEngine.Debug.LogWarning("Array size exceeded instance ports size. Excess items removed."); } serializedObject.ApplyModifiedProperties(); serializedObject.Update(); } }; if (hasArrayData) { int instancePortCount = instancePorts.Count; while (instancePortCount < arrayData.arraySize) { // Add instance port postfixed with an index number string newName = arrayData.name + " 0"; int i = 0; while (node.HasPort(newName)) { newName = arrayData.name + " " + (++i); } if (io == XNode.NodePort.IO.Output) { node.AddInstanceOutput(type, connectionType, typeConstraint, newName); } else { node.AddInstanceInput(type, connectionType, typeConstraint, newName); } EditorUtility.SetDirty(node); instancePortCount++; } while (arrayData.arraySize < instancePortCount) { arrayData.InsertArrayElementAtIndex(arrayData.arraySize); } serializedObject.ApplyModifiedProperties(); serializedObject.Update(); } if (onCreation != null) { onCreation(list); } return(list); }