1
0
mirror of https://github.com/Siccity/xNode.git synced 2026-03-26 22:49:02 +08:00

!TX(Code format)

This commit is contained in:
Icarus 2019-12-23 23:29:28 +08:00
parent f7251ee02a
commit 5d2259608e
9 changed files with 230 additions and 249 deletions

View File

@ -10,17 +10,17 @@ namespace XNodeEditor
/// </summary> /// </summary>
public class MenuPopupWindow : PopupWindowContent public class MenuPopupWindow : PopupWindowContent
{ {
public Vector2 OpenBeforeMousePos; public Vector2 openBeforeMousePos;
private SearchField _search; private SearchField search;
private MenuTreeView _menuTree; private MenuTreeView menuTree;
public Action OnCloseA; public Action onCloseAction;
public MenuPopupWindow() public MenuPopupWindow()
{ {
_search = new SearchField(); search = new SearchField();
_menuTree = new MenuTreeView(); menuTree = new MenuTreeView();
} }
private bool _isInit; private bool isInit;
/// <summary> /// <summary>
/// Add Item /// Add Item
@ -31,7 +31,7 @@ namespace XNodeEditor
/// <param name="autoClose">Automatically close window after selecting an item</param> /// <param name="autoClose">Automatically close window after selecting an item</param>
public void AddItem(string menuPath, Action onClick, char symbol = '/',bool autoClose = true) public void AddItem(string menuPath, Action onClick, char symbol = '/',bool autoClose = true)
{ {
_menuTree.AddItem(menuPath, () => menuTree.AddItem(menuPath, () =>
{ {
onClick?.Invoke(); onClick?.Invoke();
if (autoClose) if (autoClose)
@ -46,52 +46,52 @@ namespace XNodeEditor
/// </summary> /// </summary>
public void Init() public void Init()
{ {
_menuTree.Reload(); menuTree.Reload();
_isInit = true; isInit = true;
} }
public override void OnOpen() public override void OnOpen()
{ {
_search.SetFocus(); search.SetFocus();
} }
public override void OnClose() public override void OnClose()
{ {
OnCloseA?.Invoke(); onCloseAction?.Invoke();
} }
private string _str; private string _str;
public override void OnGUI(Rect rect) public override void OnGUI(Rect rect)
{ {
if (!_isInit) if (!isInit)
{ {
Init(); Init();
} }
_action(); EventAction();
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
{ {
_str = _search.OnGUI(new Rect(rect.position, new Vector2(rect.width, 20)),_str); _str = search.OnGUI(new Rect(rect.position, new Vector2(rect.width, 20)),_str);
} }
if (EditorGUI.EndChangeCheck()) if (EditorGUI.EndChangeCheck())
{ {
_menuTree.searchString = _str; menuTree.searchString = _str;
} }
_menuTree.OnGUI(new Rect(new Vector2(0,25),rect.size - new Vector2(0,20))); menuTree.OnGUI(new Rect(new Vector2(0,25),rect.size - new Vector2(0,20)));
} }
private void _action() private void EventAction()
{ {
Event e = Event.current; Event e = Event.current;
switch (e.type) switch (e.type)
{ {
case EventType.KeyDown: case EventType.KeyDown:
if (e.keyCode == KeyCode.DownArrow && !_menuTree.HasFocus()) if (e.keyCode == KeyCode.DownArrow && !menuTree.HasFocus())
{ {
_menuTree.SetFocusAndEnsureSelectedItem(); menuTree.SetFocusAndEnsureSelectedItem();
e.Use(); e.Use();
} }
break; break;

View File

@ -1,210 +1,191 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
#if ODIN_INSPECTOR #if ODIN_INSPECTOR
using Sirenix.OdinInspector.Editor; using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities; using Sirenix.Utilities;
using Sirenix.Utilities.Editor; using Sirenix.Utilities.Editor;
#endif #endif
namespace XNodeEditor { namespace XNodeEditor {
/// <summary> Base class to derive custom Node editors from. Use this to create your own custom inspectors and editors for your nodes. </summary> /// <summary> Base class to derive custom Node editors from. Use this to create your own custom inspectors and editors for your nodes. </summary>
[CustomNodeEditor(typeof(XNode.Node))] [CustomNodeEditor(typeof(XNode.Node))]
public class NodeEditor : XNodeEditor.Internal.NodeEditorBase<NodeEditor, NodeEditor.CustomNodeEditorAttribute, XNode.Node> { public class NodeEditor : XNodeEditor.Internal.NodeEditorBase<NodeEditor, NodeEditor.CustomNodeEditorAttribute, XNode.Node> {
private readonly Color DEFAULTCOLOR = new Color32(90, 97, 105, 255); private readonly Color DEFAULTCOLOR = new Color32(90, 97, 105, 255);
/// <summary> Fires every whenever a node was modified through the editor </summary> /// <summary> Fires every whenever a node was modified through the editor </summary>
public static Action<XNode.Node> onUpdateNode; public static Action<XNode.Node> onUpdateNode;
public readonly static Dictionary<XNode.NodePort, Vector2> portPositions = new Dictionary<XNode.NodePort, Vector2>(); public readonly static Dictionary<XNode.NodePort, Vector2> portPositions = new Dictionary<XNode.NodePort, Vector2>();
#if ODIN_INSPECTOR #if ODIN_INSPECTOR
internal static bool inNodeEditor = false; internal static bool inNodeEditor = false;
#endif #endif
private List<string> _excludesField; private List<string> excludesField;
public override void OnCreate() private List<string> portNames = new List<string>();
{
_excludesField = new List<string> { "m_Script", "graph", "position", "ports" }; public override void OnCreate()
{
var fields = GetExcludesField(); excludesField = new List<string> { "m_Script", "graph", "position", "ports" };
if (fields != null) var fields = GetExcludesField();
{
_excludesField.AddRange(fields); if (fields != null)
} {
} excludesField.AddRange(fields);
}
public virtual void OnHeaderGUI() { }
GUILayout.Label(target.name, NodeEditorResources.styles.nodeHeader, GUILayout.Height(30));
} public virtual void OnHeaderGUI() {
GUILayout.Label(target.name, NodeEditorResources.styles.nodeHeader, GUILayout.Height(30));
protected virtual IEnumerable<string> GetExcludesField() }
{
return null; protected virtual IEnumerable<string> GetExcludesField()
} {
return null;
/// <summary> Draws standard field editors for all public fields </summary> }
public virtual void OnBodyGUI() {
#if ODIN_INSPECTOR /// <summary> Draws standard field editors for all public fields </summary>
inNodeEditor = true; public virtual void OnBodyGUI() {
#endif #if ODIN_INSPECTOR
inNodeEditor = true;
// Unity specifically requires this to save/update any serial object. #endif
// serializedObject.Update(); must go at the start of an inspector gui, and
// serializedObject.ApplyModifiedProperties(); goes at the end. // Unity specifically requires this to save/update any serial object.
serializedObject.Update(); // serializedObject.Update(); must go at the start of an inspector gui, and
// serializedObject.ApplyModifiedProperties(); goes at the end.
#if ODIN_INSPECTOR serializedObject.Update();
InspectorUtilities.BeginDrawPropertyTree(objectTree, true);
GUIHelper.PushLabelWidth(84); #if ODIN_INSPECTOR
objectTree.Draw(true); InspectorUtilities.BeginDrawPropertyTree(objectTree, true);
InspectorUtilities.EndDrawPropertyTree(objectTree); GUIHelper.PushLabelWidth(84);
GUIHelper.PopLabelWidth(); objectTree.Draw(true);
#else InspectorUtilities.EndDrawPropertyTree(objectTree);
GUIHelper.PopLabelWidth();
// Iterate through serialized properties and draw them like the Inspector (But with ports) #else
SerializedProperty iterator = serializedObject.GetIterator();
bool enterChildren = true; // Iterate through serialized properties and draw them like the Inspector (But with ports)
List<string> _names = new List<string>(); SerializedProperty iterator = serializedObject.GetIterator();
while (iterator.NextVisible(enterChildren)) { bool enterChildren = true;
enterChildren = false; portNames.Clear();
if (_excludesField.Contains(iterator.name)) continue; while (iterator.NextVisible(enterChildren)) {
NodeEditorGUILayout.PropertyField(iterator, true); enterChildren = false;
_names.Add(iterator.name); if (excludesField.Contains(iterator.name)) continue;
} NodeEditorGUILayout.PropertyField(iterator, true);
portNames.Add(iterator.name);
//处理一下没被绘制的端口 }
foreach (var port in target.Ports)
{ //Deal with ports that are not drawn
//动态的跳过 foreach (var port in target.Ports)
if (port.IsDynamic) {
{ //Dynamic skip
continue; if (port.IsDynamic)
} {
continue;
//不受unity序列化支持,但是被标记为了输入或输出 }
if (!_names.Contains(port.fieldName))
{ //Not supported by unity serialization, but marked as input or output
NodeEditorGUILayout.PortField(port); if (!portNames.Contains(port.fieldName))
} {
} NodeEditorGUILayout.PortField(port);
#endif }
}
// Iterate through dynamic ports and draw them in the order in which they are serialized #endif
foreach (XNode.NodePort dynamicPort in target.DynamicPorts) {
if (NodeEditorGUILayout.IsDynamicPortListPort(dynamicPort)) continue; // Iterate through dynamic ports and draw them in the order in which they are serialized
NodeEditorGUILayout.PortField(dynamicPort); foreach (XNode.NodePort dynamicPort in target.DynamicPorts) {
} if (NodeEditorGUILayout.IsDynamicPortListPort(dynamicPort)) continue;
NodeEditorGUILayout.PortField(dynamicPort);
serializedObject.ApplyModifiedProperties(); }
#if ODIN_INSPECTOR serializedObject.ApplyModifiedProperties();
// Call repaint so that the graph window elements respond properly to layout changes coming from Odin
if (GUIHelper.RepaintRequested) { #if ODIN_INSPECTOR
GUIHelper.ClearRepaintRequest(); // Call repaint so that the graph window elements respond properly to layout changes coming from Odin
window.Repaint(); if (GUIHelper.RepaintRequested) {
} GUIHelper.ClearRepaintRequest();
#endif window.Repaint();
}
#if ODIN_INSPECTOR #endif
inNodeEditor = false;
#endif #if ODIN_INSPECTOR
} inNodeEditor = false;
#endif
public virtual int GetWidth() { }
Type type = target.GetType();
int width; public virtual int GetWidth() {
if (type.TryGetAttributeWidth(out width)) return width; Type type = target.GetType();
else return 208; int width;
} if (type.TryGetAttributeWidth(out width)) return width;
else return 208;
public Vector2 GetCurrentMousePosition(float yOffset = 10) }
{
return new Vector2(Event.current.mousePosition.x,Event.current.mousePosition.y + yOffset); public Vector2 GetCurrentMousePosition(float yOffset = 10)
} {
return new Vector2(Event.current.mousePosition.x,Event.current.mousePosition.y + yOffset);
/// <summary> Returns color for target node </summary> }
public virtual Color GetTint() {
// Try get color from [NodeTint] attribute /// <summary> Returns color for target node </summary>
Type type = target.GetType(); public virtual Color GetTint() {
Color color; // Try get color from [NodeTint] attribute
if (type.TryGetAttributeTint(out color)) return color; Type type = target.GetType();
// Return default color (grey) Color color;
else return DEFAULTCOLOR; if (type.TryGetAttributeTint(out color)) return color;
} // Return default color (grey)
else return DEFAULTCOLOR;
public virtual GUIStyle GetBodyStyle() { }
return NodeEditorResources.styles.nodeBody;
} public virtual GUIStyle GetBodyStyle() {
return NodeEditorResources.styles.nodeBody;
public virtual GUIStyle GetBodyHighlightStyle() { }
return NodeEditorResources.styles.nodeHighlight;
} public virtual GUIStyle GetBodyHighlightStyle() {
return NodeEditorResources.styles.nodeHighlight;
/// <summary> Add items for the context menu when right-clicking this node. Override to add custom menu items. </summary> }
public virtual void AddContextMenuItems(MenuPopupWindow menu) {
// Actions if only one node is selected /// <summary> Add items for the context menu when right-clicking this node. Override to add custom menu items. </summary>
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { public virtual void AddContextMenuItems(GenericMenu menu) {
XNode.Node node = Selection.activeObject as XNode.Node; // Actions if only one node is selected
menu.AddItem("Move To Top", () => NodeEditorWindow.current.MoveNodeToTop(node)); if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
menu.AddItem("Rename", NodeEditorWindow.current.RenameSelectedNode); XNode.Node node = Selection.activeObject as XNode.Node;
} menu.AddItem(new GUIContent("Move To Top"), false, () => NodeEditorWindow.current.MoveNodeToTop(node));
menu.AddItem(new GUIContent("Rename"), false, NodeEditorWindow.current.RenameSelectedNode);
// Add actions to any number of selected nodes }
menu.AddItem("Copy", NodeEditorWindow.current.CopySelectedNodes);
menu.AddItem("Duplicate", NodeEditorWindow.current.DuplicateSelectedNodes); // Add actions to any number of selected nodes
menu.AddItem("Remove", NodeEditorWindow.current.RemoveSelectedNodes); menu.AddItem(new GUIContent("Copy"), false, NodeEditorWindow.current.CopySelectedNodes);
menu.AddItem(new GUIContent("Duplicate"), false, NodeEditorWindow.current.DuplicateSelectedNodes);
// Custom sctions if only one node is selected menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes);
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
XNode.Node node = Selection.activeObject as XNode.Node; // Custom sctions if only one node is selected
menu.AddCustomContextMenuItems(node); if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
} XNode.Node node = Selection.activeObject as XNode.Node;
} menu.AddCustomContextMenuItems(node);
}
/// <summary> Add items for the context menu when right-clicking this node. Override to add custom menu items. </summary> }
public virtual void AddContextMenuItems(GenericMenu menu) {
// Actions if only one node is selected /// <summary> Rename the node asset. This will trigger a reimport of the node. </summary>
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { public void Rename(string newName) {
XNode.Node node = Selection.activeObject as XNode.Node; if (newName == null || newName.Trim() == "") newName = NodeEditorUtilities.NodeDefaultName(target.GetType());
menu.AddItem(new GUIContent("Move To Top"), false, () => NodeEditorWindow.current.MoveNodeToTop(node)); target.name = newName;
menu.AddItem(new GUIContent("Rename"), false, NodeEditorWindow.current.RenameSelectedNode); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
} }
// Add actions to any number of selected nodes [AttributeUsage(AttributeTargets.Class)]
menu.AddItem(new GUIContent("Copy"), false, NodeEditorWindow.current.CopySelectedNodes); public class CustomNodeEditorAttribute : Attribute,
menu.AddItem(new GUIContent("Duplicate"), false, NodeEditorWindow.current.DuplicateSelectedNodes); XNodeEditor.Internal.NodeEditorBase<NodeEditor, NodeEditor.CustomNodeEditorAttribute, XNode.Node>.INodeEditorAttrib {
menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes); private Type inspectedType;
/// <summary> Tells a NodeEditor which Node type it is an editor for </summary>
// Custom sctions if only one node is selected /// <param name="inspectedType">Type that this editor can edit</param>
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { public CustomNodeEditorAttribute(Type inspectedType) {
XNode.Node node = Selection.activeObject as XNode.Node; this.inspectedType = inspectedType;
menu.AddCustomContextMenuItems(node); }
}
} public Type GetInspectedType() {
return inspectedType;
/// <summary> Rename the node asset. This will trigger a reimport of the node. </summary> }
public void Rename(string newName) { }
if (newName == null || newName.Trim() == "") newName = NodeEditorUtilities.NodeDefaultName(target.GetType()); }
target.name = newName; }
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
}
[AttributeUsage(AttributeTargets.Class)]
public class CustomNodeEditorAttribute : Attribute,
XNodeEditor.Internal.NodeEditorBase<NodeEditor, NodeEditor.CustomNodeEditorAttribute, XNode.Node>.INodeEditorAttrib {
private Type inspectedType;
/// <summary> Tells a NodeEditor which Node type it is an editor for </summary>
/// <param name="inspectedType">Type that this editor can edit</param>
public CustomNodeEditorAttribute(Type inspectedType) {
this.inspectedType = inspectedType;
}
public Type GetInspectedType() {
return inspectedType;
}
}
}
}

View File

@ -32,13 +32,13 @@ namespace XNodeEditor {
private Rect selectionBox; private Rect selectionBox;
private bool isDoubleClick = false; private bool isDoubleClick = false;
private Vector2 lastMousePosition; private Vector2 lastMousePosition;
private MenuPopupWindow _menuPopupWindow; private MenuPopupWindow menuPopupWindow;
public void Controls() { public void Controls() {
if (_menuPopupWindow == null) if (menuPopupWindow == null)
{ {
_menuPopupWindow = new MenuPopupWindow(); menuPopupWindow = new MenuPopupWindow();
graphEditor.AddContextMenuItems(_menuPopupWindow); graphEditor.AddContextMenuItems(menuPopupWindow);
} }
wantsMouseMove = true; wantsMouseMove = true;
Event e = Event.current; Event e = Event.current;
@ -226,12 +226,12 @@ namespace XNodeEditor {
} }
// Open context menu for auto-connection // Open context menu for auto-connection
else if (NodeEditorPreferences.GetSettings().dragToCreate && autoConnectOutput != null) { else if (NodeEditorPreferences.GetSettings().dragToCreate && autoConnectOutput != null) {
_menuPopupWindow.OnCloseA = _releaseDraggedConnection; menuPopupWindow.OnCloseA = ReleaseDraggedConnection;
_menuPopupWindow.OpenBeforeMousePos = e.mousePosition; menuPopupWindow.OpenBeforeMousePos = e.mousePosition;
PopupWindow.Show(new Rect(Event.current.mousePosition, Vector2.zero),_menuPopupWindow); PopupWindow.Show(new Rect(Event.current.mousePosition, Vector2.zero),menuPopupWindow);
} }
_releaseDraggedConnection(); ReleaseDraggedConnection();
} else if (currentActivity == NodeActivity.DragNode) { } else if (currentActivity == NodeActivity.DragNode) {
IEnumerable<XNode.Node> nodes = Selection.objects.Where(x => x is XNode.Node).Select(x => x as XNode.Node); IEnumerable<XNode.Node> nodes = Selection.objects.Where(x => x is XNode.Node).Select(x => x as XNode.Node);
@ -286,8 +286,8 @@ namespace XNodeEditor {
e.Use(); // Fixes copy/paste context menu appearing in Unity 5.6.6f2 - doesn't occur in 2018.3.2f1 Probably needs to be used in other places. e.Use(); // Fixes copy/paste context menu appearing in Unity 5.6.6f2 - doesn't occur in 2018.3.2f1 Probably needs to be used in other places.
} else if (!IsHoveringNode) { } else if (!IsHoveringNode) {
autoConnectOutput = null; autoConnectOutput = null;
_menuPopupWindow.OpenBeforeMousePos = e.mousePosition; menuPopupWindow.OpenBeforeMousePos = e.mousePosition;
PopupWindow.Show(new Rect(Event.current.mousePosition, Vector2.zero),_menuPopupWindow); PopupWindow.Show(new Rect(Event.current.mousePosition, Vector2.zero),menuPopupWindow);
} }
} }
isPanning = false; isPanning = false;
@ -346,7 +346,7 @@ namespace XNodeEditor {
} }
} }
private void _releaseDraggedConnection() private void ReleaseDraggedConnection()
{ {
//Release dragged connection //Release dragged connection
draggedOutput = null; draggedOutput = null;

View File

@ -29,7 +29,7 @@ namespace XNodeEditor {
DrawConnections(); DrawConnections();
DrawNodes(); DrawNodes();
DrawSelectionBox(); DrawSelectionBox();
_drawGroupName(); DrawGroupName();
DrawTooltip(); DrawTooltip();
graphEditor.OnGUI(); graphEditor.OnGUI();
@ -42,7 +42,7 @@ namespace XNodeEditor {
GUI.matrix = m; GUI.matrix = m;
} }
private void _drawGroupName() private void DrawGroupName()
{ {
var guiContent = new GUIContent(this.graph.name); var guiContent = new GUIContent(this.graph.name);
var col = EditorStyles.label.normal.textColor; var col = EditorStyles.label.normal.textColor;

View File

@ -234,7 +234,7 @@ namespace XNodeEditor {
Color col = NodeEditorWindow.current.graphEditor.GetPortColor(port); Color col = NodeEditorWindow.current.graphEditor.GetPortColor(port);
DrawPortHandle(rect, backgroundColor, col); DrawPortHandle(rect, backgroundColor, col);
//当选择节点时显示所有的输入点索引 //Show all input point indexes when node is selected
if (port.direction == XNode.NodePort.IO.Output) if (port.direction == XNode.NodePort.IO.Output)
{ {
if (port.Connection != null && port.Connection.ConnectionCount > 1) if (port.Connection != null && port.Connection.ConnectionCount > 1)

View File

@ -75,7 +75,7 @@ namespace XNodeEditor {
return types.ToArray(); return types.ToArray();
} }
/// <summary> Find methods marked with the [ContextMenu] attribute and add them to the context menu </summary> /// <summary> Find methods marked with the [ContextMenu] attribute and add them to the menu popup window</summary>
public static void AddCustomContextMenuItems(this MenuPopupWindow contextMenu, object obj) { public static void AddCustomContextMenuItems(this MenuPopupWindow contextMenu, object obj) {
KeyValuePair<ContextMenu, MethodInfo>[] items = GetContextMenuMethods(obj); KeyValuePair<ContextMenu, MethodInfo>[] items = GetContextMenuMethods(obj);
if (items.Length != 0) { if (items.Length != 0) {

View File

@ -26,7 +26,7 @@ namespace XNodeEditor {
}); });
} }
[MenuItem("Icarus/Node Editor/Close All Editor Window")] [MenuItem("xNode/Close All Editor Window")]
static void CloseAllNodeEditorWindow() static void CloseAllNodeEditorWindow()
{ {
var windows = Resources.FindObjectsOfTypeAll<NodeEditorWindow>(); var windows = Resources.FindObjectsOfTypeAll<NodeEditorWindow>();

View File

@ -104,7 +104,7 @@ namespace XNode {
System.Type tempType = nodeType; System.Type tempType = nodeType;
while ((tempType = tempType.BaseType) != typeof(XNode.Node)) while ((tempType = tempType.BaseType) != typeof(XNode.Node))
{ {
//只返回私有的,保护等其他的不需要 // Only return private, protected, etc.
var fieldInfos = tempType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(x=>x.IsPrivate); var fieldInfos = tempType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(x=>x.IsPrivate);
fieldInfo.AddRange(fieldInfos); fieldInfo.AddRange(fieldInfos);

View File

@ -53,7 +53,7 @@ namespace XNode {
private Type valueType; private Type valueType;
#if UNITY_EDITOR #if UNITY_EDITOR
public const string FieldNameEditor = nameof(_fieldName); public const string FIELDNAMEEDITOR = nameof(_fieldName);
#endif #endif
[SerializeField] private string _fieldName; [SerializeField] private string _fieldName;
[SerializeField] private Node _node; [SerializeField] private Node _node;
@ -219,7 +219,7 @@ namespace XNode {
if (connectionType == Node.ConnectionType.Override && ConnectionCount != 0) if (connectionType == Node.ConnectionType.Override && ConnectionCount != 0)
{ {
var conPort = GetConnection(0); var conPort = GetConnection(0);
//Same connection, not disconnect
if(conPort.node != port.node || conPort != port) if(conPort.node != port.node || conPort != port)
{ {
ClearConnections(); ClearConnections();