本文共 34541 字,大约阅读时间需要 115 分钟。
孙广东 2018.5.13
Unity AssetStore中关于Node节点 编辑器相关的插件可是数不胜数, 状态机,行为树,Shader 可视化等等。
Unity自己也有 Animator的窗口使用, 还有新的Shader Graph。
现在Unity的编辑器代码已经开源了,还没有时间看。
using UnityEngine ; using UnityEditor ; using System . Collections . Generic ; public class NodeBasedEditor : EditorWindow { [ MenuItem ( "Window/Node Based Editor" )] private static void OpenWindow () { NodeBasedEditor window = GetWindow < NodeBasedEditor > (); window . titleContent = new GUIContent ( "Node Based Editor" ); } private void OnGUI () { DrawNodes (); ProcessEvents ( Event . current ); if ( GUI . changed ) Repaint (); } private void DrawNodes () { } private void ProcessEvents ( Event e ) { } } |
using System ; using UnityEditor ; using UnityEngine ; public class Node { public Rect rect ; public string title ; public GUIStyle style ; public Node ( Vector2 position , float width , float height , GUIStyle nodeStyle ) { rect = new Rect ( position . x , position . y , width , height ); style = nodeStyle ; } public void Drag ( Vector2 delta ) { rect . position += delta ; } public void Draw () { GUI . Box ( rect , title , style ); } public bool ProcessEvents ( Event e ) { return false ; } } |
using UnityEngine ; using UnityEditor ; using System . Collections . Generic ; public class NodeBasedEditor : EditorWindow { private List < Node > nodes ; [ MenuItem ( "Window/Node Based Editor" )] private static void OpenWindow () { NodeBasedEditor window = GetWindow < NodeBasedEditor > (); window . titleContent = new GUIContent ( "Node Based Editor" ); } private void OnGUI () { DrawNodes (); ProcessEvents ( Event . current ); if ( GUI . changed ) Repaint (); } private void DrawNodes () { if ( nodes != null ) { for ( int i = 0 ; i < nodes . Count ; i ++ ) { nodes [ i ]. Draw (); } } } private void ProcessEvents ( Event e ) { } } |
using UnityEngine ; using UnityEditor ; using System . Collections . Generic ; public class NodeBasedEditor : EditorWindow { private List < Node > nodes ; private GUIStyle nodeStyle ; [ MenuItem ( "Window/Node Based Editor" )] private static void OpenWindow () { NodeBasedEditor window = GetWindow < NodeBasedEditor > (); window . titleContent = new GUIContent ( "Node Based Editor" ); } private void OnEnable () { nodeStyle = new GUIStyle (); nodeStyle . normal . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/node1.png" ) as Texture2D ; nodeStyle . border = new RectOffset ( 12 , 12 , 12 , 12 ); } private void OnGUI () { DrawNodes (); ProcessEvents ( Event . current ); if ( GUI . changed ) Repaint (); } private void DrawNodes () { if ( nodes != null ) { for ( int i = 0 ; i < nodes . Count ; i ++ ) { nodes [ i ]. Draw (); } } } private void ProcessEvents ( Event e ) { switch ( e . type ) { case EventType . MouseDown : if ( e . button == 1 ) { ProcessContextMenu ( e . mousePosition ); } break ; } } private void ProcessContextMenu ( Vector2 mousePosition ) { GenericMenu genericMenu = new GenericMenu (); genericMenu . AddItem ( new GUIContent ( "Add node" ), false , () => OnClickAddNode ( mousePosition )); genericMenu . ShowAsContext (); } private void OnClickAddNode ( Vector2 mousePosition ) { if ( nodes == null ) { nodes = new List < Node > (); } nodes . Add ( new Node ( mousePosition , 200 , 50 , nodeStyle )); } } |
using System ; using UnityEditor ; using UnityEngine ; public class Node { public Rect rect ; public string title ; public bool isDragged ; public GUIStyle style ; public Node ( Vector2 position , float width , float height , GUIStyle nodeStyle ) { rect = new Rect ( position . x , position . y , width , height ); style = nodeStyle ; } public void Drag ( Vector2 delta ) { rect . position += delta ; } public void Draw () { GUI . Box ( rect , title , style ); } public bool ProcessEvents ( Event e ) { switch ( e . type ) { case EventType . MouseDown : if ( e . button == 0 ) { if ( rect . Contains ( e . mousePosition )) { isDragged = true ; GUI . changed = true ; } else { GUI . changed = true ; } } break ; case EventType . MouseUp : isDragged = false ; break ; case EventType . MouseDrag : if ( e . button == 0 && isDragged ) { Drag ( e . delta ); e . Use (); return true ; } break ; } return false ; } } |
private void OnGUI () { DrawNodes (); ProcessNodeEvents ( Event . current ); ProcessEvents ( Event . current ); if ( GUI . changed ) Repaint (); } private void DrawNodes () { if ( nodes != null ) { for ( int i = 0 ; i < nodes . Count ; i ++ ) { nodes [ i ]. Draw (); } } } private void ProcessEvents ( Event e ) { switch ( e . type ) { case EventType . MouseDown : if ( e . button == 1 ) { ProcessContextMenu ( e . mousePosition ); } break ; } } private void ProcessNodeEvents ( Event e ) { if ( nodes != null ) { for ( int i = nodes . Count - 1 ; i >= 0 ; i -- ) { bool guiChanged = nodes [ i ]. ProcessEvents ( e ); if ( guiChanged ) { GUI . changed = true ; } } } } private void ProcessContextMenu ( Vector2 mousePosition ) { GenericMenu genericMenu = new GenericMenu (); genericMenu . AddItem ( new GUIContent ( "Add node" ), false , () => OnClickAddNode ( mousePosition )); genericMenu . ShowAsContext (); } |
using System ; using UnityEngine ; public enum ConnectionPointType { In , Out } public class ConnectionPoint { public Rect rect ; public ConnectionPointType type ; public Node node ; public GUIStyle style ; public Action < ConnectionPoint > OnClickConnectionPoint ; public ConnectionPoint ( Node node , ConnectionPointType type , GUIStyle style , Action < ConnectionPoint > OnClickConnectionPoint ) { this . node = node ; this . type = type ; this . style = style ; this . OnClickConnectionPoint = OnClickConnectionPoint ; rect = new Rect ( 0 , 0 , 10f , 20f ); } public void Draw () { rect . y = node . rect . y + ( node . rect . height * 0.5f ) - rect . height * 0.5f ; switch ( type ) { case ConnectionPointType . In : rect . x = node . rect . x - rect . width + 8f ; break ; case ConnectionPointType . Out : rect . x = node . rect . x + node . rect . width - 8f ; break ; } if ( GUI . Button ( rect , "" , style )) { if ( OnClickConnectionPoint != null ) { OnClickConnectionPoint ( this ); } } } } |
using System ; using UnityEditor ; using UnityEngine ; public class Connection { public ConnectionPoint inPoint ; public ConnectionPoint outPoint ; public Action < Connection > OnClickRemoveConnection ; public Connection ( ConnectionPoint inPoint , ConnectionPoint outPoint , Action < Connection > OnClickRemoveConnection ) { this . inPoint = inPoint ; this . outPoint = outPoint ; this . OnClickRemoveConnection = OnClickRemoveConnection ; } public void Draw () { Handles . DrawBezier ( inPoint . rect . center , outPoint . rect . center , inPoint . rect . center + Vector2 . left * 50f , outPoint . rect . center - Vector2 . left * 50f , Color . white , null , 2f ); if ( Handles . Button (( inPoint . rect . center + outPoint . rect . center ) * 0.5f , Quaternion . identity , 4 , 8 , Handles . RectangleCap )) { if ( OnClickRemoveConnection != null ) { OnClickRemoveConnection ( this ); } } } } |
using System ; using UnityEditor ; using UnityEngine ; public class Node { public Rect rect ; public string title ; public bool isDragged ; public ConnectionPoint inPoint ; public ConnectionPoint outPoint ; public GUIStyle style ; public Node ( Vector2 position , float width , float height , GUIStyle nodeStyle , GUIStyle inPointStyle , GUIStyle outPointStyle , Action < ConnectionPoint > OnClickInPoint , Action < ConnectionPoint > OnClickOutPoint ) { rect = new Rect ( position . x , position . y , width , height ); style = nodeStyle ; inPoint = new ConnectionPoint ( this , ConnectionPointType . In , inPointStyle , OnClickInPoint ); outPoint = new ConnectionPoint ( this , ConnectionPointType . Out , outPointStyle , OnClickOutPoint ); } public void Drag ( Vector2 delta ) { rect . position += delta ; } public void Draw () { inPoint . Draw (); outPoint . Draw (); GUI . Box ( rect , title , style ); } public bool ProcessEvents ( Event e ) { switch ( e . type ) { case EventType . MouseDown : if ( e . button == 0 ) { if ( rect . Contains ( e . mousePosition )) { isDragged = true ; GUI . changed = true ; } else { GUI . changed = true ; } } break ; case EventType . MouseUp : isDragged = false ; break ; case EventType . MouseDrag : if ( e . button == 0 && isDragged ) { Drag ( e . delta ); e . Use (); return true ; } break ; } return false ; } } |
using UnityEngine ; using UnityEditor ; using System . Collections . Generic ; public class NodeBasedEditor : EditorWindow { private List < Node > nodes ; private List < Connection > connections ; private GUIStyle nodeStyle ; private GUIStyle inPointStyle ; private GUIStyle outPointStyle ; private ConnectionPoint selectedInPoint ; private ConnectionPoint selectedOutPoint ; [ MenuItem ( "Window/Node Based Editor" )] private static void OpenWindow () { NodeBasedEditor window = GetWindow < NodeBasedEditor > (); window . titleContent = new GUIContent ( "Node Based Editor" ); } private void OnEnable () { nodeStyle = new GUIStyle (); nodeStyle . normal . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/node1.png" ) as Texture2D ; nodeStyle . border = new RectOffset ( 12 , 12 , 12 , 12 ); inPointStyle = new GUIStyle (); inPointStyle . normal . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/btn left.png" ) as Texture2D ; inPointStyle . active . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/btn left on.png" ) as Texture2D ; inPointStyle . border = new RectOffset ( 4 , 4 , 12 , 12 ); outPointStyle = new GUIStyle (); outPointStyle . normal . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/btn right.png" ) as Texture2D ; outPointStyle . active . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/btn right on.png" ) as Texture2D ; outPointStyle . border = new RectOffset ( 4 , 4 , 12 , 12 ); } private void OnGUI () { DrawNodes (); DrawConnections (); ProcessNodeEvents ( Event . current ); ProcessEvents ( Event . current ); if ( GUI . changed ) Repaint (); } private void DrawNodes () { if ( nodes != null ) { for ( int i = 0 ; i < nodes . Count ; i ++ ) { nodes [ i ]. Draw (); } } } private void DrawConnections () { if ( connections != null ) { for ( int i = 0 ; i < connections . Count ; i ++ ) { connections [ i ]. Draw (); } } } private void ProcessEvents ( Event e ) { switch ( e . type ) { case EventType . MouseDown : if ( e . button == 0 ) { ClearConnectionSelection (); } if ( e . button == 1 ) { ProcessContextMenu ( e . mousePosition ); } break ; } } private void ProcessNodeEvents ( Event e ) { if ( nodes != null ) { for ( int i = nodes . Count - 1 ; i >= 0 ; i -- ) { bool guiChanged = nodes [ i ]. ProcessEvents ( e ); if ( guiChanged ) { GUI . changed = true ; } } } } private void ProcessContextMenu ( Vector2 mousePosition ) { GenericMenu genericMenu = new GenericMenu (); genericMenu . AddItem ( new GUIContent ( "Add node" ), false , () => OnClickAddNode ( mousePosition )); genericMenu . ShowAsContext (); } private void OnClickAddNode ( Vector2 mousePosition ) { if ( nodes == null ) { nodes = new List < Node > (); } nodes . Add ( new Node ( mousePosition , 200 , 50 , nodeStyle , inPointStyle , outPointStyle , OnClickInPoint , OnClickOutPoint )); } private void OnClickInPoint ( ConnectionPoint inPoint ) { selectedInPoint = inPoint ; if ( selectedOutPoint != null ) { if ( selectedOutPoint . node != selectedInPoint . node ) { CreateConnection (); ClearConnectionSelection (); } else { ClearConnectionSelection (); } } } private void OnClickOutPoint ( ConnectionPoint outPoint ) { selectedOutPoint = outPoint ; if ( selectedInPoint != null ) { if ( selectedOutPoint . node != selectedInPoint . node ) { CreateConnection (); ClearConnectionSelection (); } else { ClearConnectionSelection (); } } } private void OnClickRemoveConnection ( Connection connection ) { connections . Remove ( connection ); } private void CreateConnection () { if ( connections == null ) { connections = new List < Connection > (); } connections . Add ( new Connection ( selectedInPoint , selectedOutPoint , OnClickRemoveConnection )); } private void ClearConnectionSelection () { selectedInPoint = null ; selectedOutPoint = null ; } } |
using System ; using UnityEditor ; using UnityEngine ; public class Node { public Rect rect ; public string title ; public bool isDragged ; public bool isSelected ; public ConnectionPoint inPoint ; public ConnectionPoint outPoint ; public GUIStyle style ; public GUIStyle defaultNodeStyle ; public GUIStyle selectedNodeStyle ; public Node ( Vector2 position , float width , float height , GUIStyle nodeStyle , GUIStyle selectedStyle , GUIStyle inPointStyle , GUIStyle outPointStyle , Action < ConnectionPoint > OnClickInPoint , Action < ConnectionPoint > OnClickOutPoint ) { rect = new Rect ( position . x , position . y , width , height ); style = nodeStyle ; inPoint = new ConnectionPoint ( this , ConnectionPointType . In , inPointStyle , OnClickInPoint ); outPoint = new ConnectionPoint ( this , ConnectionPointType . Out , outPointStyle , OnClickOutPoint ); defaultNodeStyle = nodeStyle ; selectedNodeStyle = selectedStyle ; } public void Drag ( Vector2 delta ) { rect . position += delta ; } public void Draw () { inPoint . Draw (); outPoint . Draw (); GUI . Box ( rect , title , style ); } public bool ProcessEvents ( Event e ) { switch ( e . type ) { case EventType . MouseDown : if ( e . button == 0 ) { if ( rect . Contains ( e . mousePosition )) { isDragged = true ; GUI . changed = true ; isSelected = true ; style = selectedNodeStyle ; } else { GUI . changed = true ; isSelected = false ; style = defaultNodeStyle ; } } break ; case EventType . MouseUp : isDragged = false ; break ; case EventType . MouseDrag : if ( e . button == 0 && isDragged ) { Drag ( e . delta ); e . Use (); return true ; } break ; } return false ; } } |
using UnityEngine ; using UnityEditor ; using System . Collections . Generic ; public class NodeBasedEditor : EditorWindow { private List < Node > nodes ; private List < Connection > connections ; private GUIStyle nodeStyle ; private GUIStyle selectedNodeStyle ; private GUIStyle inPointStyle ; private GUIStyle outPointStyle ; private ConnectionPoint selectedInPoint ; private ConnectionPoint selectedOutPoint ; [ MenuItem ( "Window/Node Based Editor" )] private static void OpenWindow () { NodeBasedEditor window = GetWindow < NodeBasedEditor > (); window . titleContent = new GUIContent ( "Node Based Editor" ); } private void OnEnable () { nodeStyle = new GUIStyle (); nodeStyle . normal . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/node1.png" ) as Texture2D ; nodeStyle . border = new RectOffset ( 12 , 12 , 12 , 12 ); selectedNodeStyle = new GUIStyle (); selectedNodeStyle . normal . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/node1 on.png" ) as Texture2D ; selectedNodeStyle . border = new RectOffset ( 12 , 12 , 12 , 12 ); inPointStyle = new GUIStyle (); inPointStyle . normal . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/btn left.png" ) as Texture2D ; inPointStyle . active . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/btn left on.png" ) as Texture2D ; inPointStyle . border = new RectOffset ( 4 , 4 , 12 , 12 ); outPointStyle = new GUIStyle (); outPointStyle . normal . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/btn right.png" ) as Texture2D ; outPointStyle . active . background = EditorGUIUtility . Load ( "builtin skins/darkskin/images/btn right on.png" ) as Texture2D ; outPointStyle . border = new RectOffset ( 4 , 4 , 12 , 12 ); } ... |
private void OnClickAddNode ( Vector2 mousePosition ) { if ( nodes == null ) { nodes = new List < Node > (); } nodes . Add ( new Node ( mousePosition , 200 , 50 , nodeStyle , selectedNodeStyle , inPointStyle , outPointStyle , OnClickInPoint , OnClickOutPoint )); } |
using System ; using UnityEditor ; using UnityEngine ; public class Node { public Rect rect ; public string title ; public bool isDragged ; public bool isSelected ; public ConnectionPoint inPoint ; public ConnectionPoint outPoint ; public GUIStyle style ; public GUIStyle defaultNodeStyle ; public GUIStyle selectedNodeStyle ; public Action < Node > OnRemoveNode ; public Node ( Vector2 position , float width , float height , GUIStyle nodeStyle , GUIStyle selectedStyle , GUIStyle inPointStyle , GUIStyle outPointStyle , Action < ConnectionPoint > OnClickInPoint , Action < ConnectionPoint > OnClickOutPoint , Action < Node > OnClickRemoveNode ) { rect = new Rect ( position . x , position . y , width , height ); style = nodeStyle ; inPoint = new ConnectionPoint ( this , ConnectionPointType . In , inPointStyle , OnClickInPoint ); outPoint = new ConnectionPoint ( this , ConnectionPointType . Out , outPointStyle , OnClickOutPoint ); defaultNodeStyle = nodeStyle ; selectedNodeStyle = selectedStyle ; OnRemoveNode = OnClickRemoveNode ; } public void Drag ( Vector2 delta ) { rect . position += delta ; } public void Draw () { inPoint . Draw (); outPoint . Draw (); GUI . Box ( rect , title , style ); } public bool ProcessEvents ( Event e ) { switch ( e . type ) { case EventType . MouseDown : if ( e . button == 0 ) { if ( rect . Contains ( e . mousePosition )) { isDragged = true ; GUI . changed = true ; isSelected = true ; style = selectedNodeStyle ; } else { GUI . changed = true ; isSelected = false ; style = defaultNodeStyle ; } } if ( e . button == 1 && isSelected && rect . Contains ( e . mousePosition )) { ProcessContextMenu (); e . Use (); } break ; case EventType . MouseUp : isDragged = false ; break ; case EventType . MouseDrag : if ( e . button == 0 && isDragged ) { Drag ( e . delta ); e . Use (); return true ; } break ; } return false ; } private void ProcessContextMenu () { GenericMenu genericMenu = new GenericMenu (); genericMenu . AddItem ( new GUIContent ( "Remove node" ), false , OnClickRemoveNode ); genericMenu . ShowAsContext (); } private void OnClickRemoveNode () { if ( OnRemoveNode != null ) { OnRemoveNode ( this ); } } } |
private void OnClickAddNode ( Vector2 mousePosition ) { if ( nodes == null ) { nodes = new List < Node > (); } nodes . Add ( new Node ( mousePosition , 200 , 50 , nodeStyle , selectedNodeStyle , inPointStyle , outPointStyle , OnClickInPoint , OnClickOutPoint , OnClickRemoveNode )); } |
private void OnClickRemoveNode ( Node node ) { if ( connections != null ) { List < Connection > connectionsToRemove = new List < Connection > (); for ( int i = 0 ; i < connections . Count ; i ++ ) { if ( connections [ i ]. inPoint == node . inPoint || connections [ i ]. outPoint == node . outPoint ) { connectionsToRemove . Add ( connections [ i ]); } } for ( int i = 0 ; i < connectionsToRemove . Count ; i ++ ) { connections . Remove ( connectionsToRemove [ i ]); } connectionsToRemove = null ; } nodes . Remove ( node ); } |
public class NodeBasedEditor : EditorWindow { private List < Node > nodes ; private List < Connection > connections ; private GUIStyle nodeStyle ; private GUIStyle selectedNodeStyle ; private GUIStyle inPointStyle ; private GUIStyle outPointStyle ; private ConnectionPoint selectedInPoint ; private ConnectionPoint selectedOutPoint ; private Vector2 drag ; ... |
private void ProcessEvents ( Event e ) { drag = Vector2 . zero ; switch ( e . type ) { case EventType . MouseDown : if ( e . button == 0 ) { ClearConnectionSelection (); } if ( e . button == 1 ) { ProcessContextMenu ( e . mousePosition ); } break ; case EventType . MouseDrag : if ( e . button == 0 ) { OnDrag ( e . delta ); } break ; } } |
private void OnDrag ( Vector2 delta ) { drag = delta ; if ( nodes != null ) { for ( int i = 0 ; i < nodes . Count ; i ++ ) { nodes [ i ]. Drag ( delta ); } } GUI . changed = true ; } |
private void OnGUI () { DrawNodes (); DrawConnections (); DrawConnectionLine ( Event . current ); ProcessNodeEvents ( Event . current ); ProcessEvents ( Event . current ); if ( GUI . changed ) Repaint (); } |
private void DrawConnectionLine ( Event e ) { if ( selectedInPoint != null && selectedOutPoint == null ) { Handles . DrawBezier ( selectedInPoint . rect . center , e . mousePosition , selectedInPoint . rect . center + Vector2 . left * 50f , e . mousePosition - Vector2 . left * 50f , Color . white , null , 2f ); GUI . changed = true ; } if ( selectedOutPoint != null && selectedInPoint == null ) { Handles . DrawBezier ( selectedOutPoint . rect . center , e . mousePosition , selectedOutPoint . rect . center - Vector2 . left * 50f , e . mousePosition + Vector2 . left * 50f , Color . white , null , 2f ); GUI . changed = true ; } } |
public class NodeBasedEditor : EditorWindow { private List < Node > nodes ; private List < Connection > connections ; private GUIStyle nodeStyle ; private GUIStyle selectedNodeStyle ; private GUIStyle inPointStyle ; private GUIStyle outPointStyle ; private ConnectionPoint selectedInPoint ; private ConnectionPoint selectedOutPoint ; private Vector2 offset ; private Vector2 drag ; ... |
private void OnGUI () { DrawGrid ( 20 , 0.2f , Color . gray ); DrawGrid ( 100 , 0.4f , Color . gray ); DrawNodes (); DrawConnections (); DrawConnectionLine ( Event . current ); ProcessNodeEvents ( Event . current ); ProcessEvents ( Event . current ); if ( GUI . changed ) Repaint (); } private void DrawGrid ( float gridSpacing , float gridOpacity , Color gridColor ) { int widthDivs = Mathf . CeilToInt ( position . width / gridSpacing ); int heightDivs = Mathf . CeilToInt ( position . height / gridSpacing ); Handles . BeginGUI (); Handles . color = new Color ( gridColor . r , gridColor . g , gridColor . b , gridOpacity ); offset += drag * 0.5f ; Vector3 newOffset = new Vector3 ( offset . x % gridSpacing , offset . y % gridSpacing , 0 ); for ( int i = 0 ; i < widthDivs ; i ++ ) { Handles . DrawLine ( new Vector3 ( gridSpacing * i , - gridSpacing , 0 ) + newOffset , new Vector3 ( gridSpacing * i , position . height , 0f ) + newOffset ); } for ( int j = 0 ; j < heightDivs ; j ++ ) { Handles . DrawLine ( new Vector3 ( - gridSpacing , gridSpacing * j , 0 ) + newOffset , new Vector3 ( position . width , gridSpacing * j , 0f ) + newOffset ); } Handles . color = Color . white ; Handles . EndGUI (); } |
using UnityEngine; using UnityEditor; using System.Collections.Generic; public class NodeBasedEditor : EditorWindow { private List<Node> nodes; private List<Connection> connections; private GUIStyle nodeStyle; private GUIStyle selectedNodeStyle; private GUIStyle inPointStyle; private GUIStyle outPointStyle; private ConnectionPoint selectedInPoint; private ConnectionPoint selectedOutPoint; private Vector2 offset; private Vector2 drag; [MenuItem("Window/Node Based Editor")] private static void OpenWindow() { NodeBasedEditor window = GetWindow<NodeBasedEditor>(); window.titleContent = new GUIContent("Node Based Editor"); } private void OnEnable() { nodeStyle = new GUIStyle(); nodeStyle.normal.background = EditorGUIUtility.Load("builtin skins/darkskin/images/node1.png") as Texture2D; nodeStyle.border = new RectOffset(12, 12, 12, 12); selectedNodeStyle = new GUIStyle(); selectedNodeStyle.normal.background = EditorGUIUtility.Load("builtin skins/darkskin/images/node1 on.png") as Texture2D; selectedNodeStyle.border = new RectOffset(12, 12, 12, 12); inPointStyle = new GUIStyle(); inPointStyle.normal.background = EditorGUIUtility.Load("builtin skins/darkskin/images/btn left.png") as Texture2D; inPointStyle.active.background = EditorGUIUtility.Load("builtin skins/darkskin/images/btn left on.png") as Texture2D; inPointStyle.border = new RectOffset(4, 4, 12, 12); outPointStyle = new GUIStyle(); outPointStyle.normal.background = EditorGUIUtility.Load("builtin skins/darkskin/images/btn right.png") as Texture2D; outPointStyle.active.background = EditorGUIUtility.Load("builtin skins/darkskin/images/btn right on.png") as Texture2D; outPointStyle.border = new RectOffset(4, 4, 12, 12); } private void OnGUI() { DrawGrid(20, 0.2f, Color.gray); DrawGrid(100, 0.4f, Color.gray); DrawNodes(); DrawConnections(); DrawConnectionLine(Event.current); ProcessNodeEvents(Event.current); ProcessEvents(Event.current); if (GUI.changed) Repaint(); } private void DrawGrid(float gridSpacing, float gridOpacity, Color gridColor) { int widthDivs = Mathf.CeilToInt(position.width / gridSpacing); int heightDivs = Mathf.CeilToInt(position.height / gridSpacing); Handles.BeginGUI(); Handles.color = new Color(gridColor.r, gridColor.g, gridColor.b, gridOpacity); offset += drag * 0.5f; Vector3 newOffset = new Vector3(offset.x % gridSpacing, offset.y % gridSpacing, 0); for (int i = 0; i < widthDivs; i++) { Handles.DrawLine(new Vector3(gridSpacing * i, -gridSpacing, 0) + newOffset, new Vector3(gridSpacing * i, position.height, 0f) + newOffset); } for (int j = 0; j < heightDivs; j++) { Handles.DrawLine(new Vector3(-gridSpacing, gridSpacing * j, 0) + newOffset, new Vector3(position.width, gridSpacing * j, 0f) + newOffset); } Handles.color = Color.white; Handles.EndGUI(); } private void DrawNodes() { if (nodes != null) { for (int i = 0; i < nodes.Count; i++) { nodes[i].Draw(); } } } private void DrawConnections() { if (connections != null) { for (int i = 0; i < connections.Count; i++) { connections[i].Draw(); } } } private void ProcessEvents(Event e) { drag = Vector2.zero; switch (e.type) { case EventType.MouseDown: if (e.button == 0) { ClearConnectionSelection(); } if (e.button == 1) { ProcessContextMenu(e.mousePosition); } break; case EventType.MouseDrag: if (e.button == 0) { OnDrag(e.delta); } break; } } private void ProcessNodeEvents(Event e) { if (nodes != null) { for (int i = nodes.Count - 1; i >= 0; i--) { bool guiChanged = nodes[i].ProcessEvents(e); if (guiChanged) { GUI.changed = true; } } } } private void DrawConnectionLine(Event e) { if (selectedInPoint != null && selectedOutPoint == null) { Handles.DrawBezier( selectedInPoint.rect.center, e.mousePosition, selectedInPoint.rect.center + Vector2.left * 50f, e.mousePosition - Vector2.left * 50f, Color.white, null, 2f ); GUI.changed = true; } if (selectedOutPoint != null && selectedInPoint == null) { Handles.DrawBezier( selectedOutPoint.rect.center, e.mousePosition, selectedOutPoint.rect.center - Vector2.left * 50f, e.mousePosition + Vector2.left * 50f, Color.white, null, 2f ); GUI.changed = true; } } private void ProcessContextMenu(Vector2 mousePosition) { GenericMenu genericMenu = new GenericMenu(); genericMenu.AddItem(new GUIContent("Add node"), false, () => OnClickAddNode(mousePosition)); genericMenu.ShowAsContext(); } private void OnDrag(Vector2 delta) { drag = delta; if (nodes != null) { for (int i = 0; i < nodes.Count; i++) { nodes[i].Drag(delta); } } GUI.changed = true; } private void OnClickAddNode(Vector2 mousePosition) { if (nodes == null) { nodes = new List<Node>(); } nodes.Add(new Node(mousePosition, 200, 50, nodeStyle, selectedNodeStyle, inPointStyle, outPointStyle, OnClickInPoint, OnClickOutPoint, OnClickRemoveNode)); } private void OnClickInPoint(ConnectionPoint inPoint) { selectedInPoint = inPoint; if (selectedOutPoint != null) { if (selectedOutPoint.node != selectedInPoint.node) { CreateConnection(); ClearConnectionSelection(); } else { ClearConnectionSelection(); } } } private void OnClickOutPoint(ConnectionPoint outPoint) { selectedOutPoint = outPoint; if (selectedInPoint != null) { if (selectedOutPoint.node != selectedInPoint.node) { CreateConnection(); ClearConnectionSelection(); } else { ClearConnectionSelection(); } } } private void OnClickRemoveNode(Node node) { if (connections != null) { List<Connection> connectionsToRemove = new List<Connection>(); for (int i = 0; i < connections.Count; i++) { if (connections[i].inPoint == node.inPoint || connections[i].outPoint == node.outPoint) { connectionsToRemove.Add(connections[i]); } } for (int i = 0; i < connectionsToRemove.Count; i++) { connections.Remove(connectionsToRemove[i]); } connectionsToRemove = null; } nodes.Remove(node); } private void OnClickRemoveConnection(Connection connection) { connections.Remove(connection); } private void CreateConnection() { if (connections == null) { connections = new List<Connection>(); } connections.Add(new Connection(selectedInPoint, selectedOutPoint, OnClickRemoveConnection)); } private void ClearConnectionSelection() { selectedInPoint = null; selectedOutPoint = null; } } |
using System; using UnityEditor; using UnityEngine; public class Node { public Rect rect; public string title; public bool isDragged; public bool isSelected; public ConnectionPoint inPoint; public ConnectionPoint outPoint; public GUIStyle style; public GUIStyle defaultNodeStyle; public GUIStyle selectedNodeStyle; public Action<Node> OnRemoveNode; public Node(Vector2 position, float width, float height, GUIStyle nodeStyle, GUIStyle selectedStyle, GUIStyle inPointStyle, GUIStyle outPointStyle, Action<ConnectionPoint> OnClickInPoint, Action<ConnectionPoint> OnClickOutPoint, Action<Node> OnClickRemoveNode) { rect = new Rect(position.x, position.y, width, height); style = nodeStyle; inPoint = new ConnectionPoint(this, ConnectionPointType.In, inPointStyle, OnClickInPoint); outPoint = new ConnectionPoint(this, ConnectionPointType.Out, outPointStyle, OnClickOutPoint); defaultNodeStyle = nodeStyle; selectedNodeStyle = selectedStyle; OnRemoveNode = OnClickRemoveNode; } public void Drag(Vector2 delta) { rect.position += delta; } public void Draw() { inPoint.Draw(); outPoint.Draw(); GUI.Box(rect, title, style); } public bool ProcessEvents(Event e) { switch (e.type) { case EventType.MouseDown: if (e.button == 0) { if (rect.Contains(e.mousePosition)) { isDragged = true; GUI.changed = true; isSelected = true; style = selectedNodeStyle; } else { GUI.changed = true; isSelected = false; style = defaultNodeStyle; } } if (e.button == 1 && isSelected && rect.Contains(e.mousePosition)) { ProcessContextMenu(); e.Use(); } break; case EventType.MouseUp: isDragged = false; break; case EventType.MouseDrag: if (e.button == 0 && isDragged) { Drag(e.delta); e.Use(); return true; } break; } return false; } private void ProcessContextMenu() { GenericMenu genericMenu = new GenericMenu(); genericMenu.AddItem(new GUIContent("Remove node"), false, OnClickRemoveNode); genericMenu.ShowAsContext(); } private void OnClickRemoveNode() { if (OnRemoveNode != null) { OnRemoveNode(this); } } } |
using System; using UnityEditor; using UnityEngine; public class Connection { public ConnectionPoint inPoint; public ConnectionPoint outPoint; public Action<Connection> OnClickRemoveConnection; public Connection(ConnectionPoint inPoint, ConnectionPoint outPoint, Action<Connection> OnClickRemoveConnection) { this.inPoint = inPoint; this.outPoint = outPoint; this.OnClickRemoveConnection = OnClickRemoveConnection; } public void Draw() { Handles.DrawBezier( inPoint.rect.center, outPoint.rect.center, inPoint.rect.center + Vector2.left * 50f, outPoint.rect.center - Vector2.left * 50f, Color.white, null, 2f ); if (Handles.Button((inPoint.rect.center + outPoint.rect.center) * 0.5f, Quaternion.identity, 4, 8, Handles.RectangleCap)) { if (OnClickRemoveConnection != null) { OnClickRemoveConnection(this); } } } } |
using System; using UnityEngine; public enum ConnectionPointType { In, Out } public class ConnectionPoint { public Rect rect; public ConnectionPointType type; public Node node; public GUIStyle style; public Action<ConnectionPoint> OnClickConnectionPoint; public ConnectionPoint(Node node, ConnectionPointType type, GUIStyle style, Action<ConnectionPoint> OnClickConnectionPoint) { this.node = node; this.type = type; this.style = style; this.OnClickConnectionPoint = OnClickConnectionPoint; rect = new Rect(0, 0, 10f, 20f); } public void Draw() { rect.y = node.rect.y + (node.rect.height * 0.5f) - rect.height * 0.5f; switch (type) { case ConnectionPointType.In: rect.x = node.rect.x - rect.width + 8f; break; case ConnectionPointType.Out: rect.x = node.rect.x + node.rect.width - 8f; break; } if (GUI.Button(rect, "", style)) { if (OnClickConnectionPoint != null) { OnClickConnectionPoint(this); } } } } |
转载地址:http://qkla.baihongyu.com/