diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs index 1c4aac0..3c2cbe4 100644 --- a/Scripts/Editor/NodeEditorAction.cs +++ b/Scripts/Editor/NodeEditorAction.cs @@ -7,10 +7,10 @@ using UNEC; public static class NodeEditorAction { - public static NodeEditorWindow window { get { return NodeEditorWindow.window; } } public static bool dragging; + public static Vector2 dragOffset; - public static void Controls() { + public static void Controls(NodeEditorWindow window) { Event e = Event.current; switch (e.type) { @@ -20,35 +20,46 @@ public static class NodeEditorAction { else window.zoom -= 0.1f * window.zoom; break; case EventType.MouseDrag: - if (e.button == 1) { + if (e.button == 0) { + if (window.activeNode != null) { + window.activeNode.position.position = window.WindowToGridPosition(e.mousePosition) + dragOffset; + window.Repaint(); + } + } + else if (e.button == 1) { window.panOffset += e.delta * window.zoom; dragging = true; } break; case EventType.KeyDown: - if (e.keyCode == KeyCode.F) Focus(); + if (e.keyCode == KeyCode.F) Focus(window); break; - case EventType.mouseDown: + case EventType.MouseDown: dragging = false; + window.SelectNode(window.hoveredNode); + if (window.hoveredNode != null) { + dragOffset = window.hoveredNode.position.position - window.WindowToGridPosition(e.mousePosition); + } + window.Repaint(); break; case EventType.MouseUp: if (dragging) return; + if (e.button == 1) { - NodeEditorGUI.RightClickContextMenu(); + NodeEditorGUI.RightClickContextMenu(window); } break; } } /// Puts all nodes in focus. If no nodes are present, resets view to - public static void Focus() { + public static void Focus(this NodeEditorWindow window) { window.zoom = 2; window.panOffset = Vector2.zero; } - public static void CreateNode(Type type, Vector2 position) { - Node node = window.currentGraph.AddNode(type); - Debug.Log("SetNode " + position); + public static void CreateNode(this NodeEditorWindow window, Type type, Vector2 position) { + Node node = window.graph.AddNode(type); node.position.position = position; } } diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs index ede6754..b897355 100644 --- a/Scripts/Editor/NodeEditorGUI.cs +++ b/Scripts/Editor/NodeEditorGUI.cs @@ -8,7 +8,27 @@ namespace UNEC { /// Contains GUI methods public static class NodeEditorGUI { - public static NodeEditorWindow window { get { return NodeEditorWindow.window; } } + public static void BeginZoomed(Rect rect, float zoom) { + GUI.EndClip(); + + GUIUtility.ScaleAroundPivot(Vector2.one / zoom, rect.size * 0.5f); + Vector4 padding = new Vector4(0, 22, 0, 0); + padding *= zoom; + GUI.BeginClip(new Rect( + -((rect.width * zoom) - rect.width) * 0.5f, + -(((rect.height * zoom) - rect.height) * 0.5f) + (22 * zoom), + rect.width * zoom, + rect.height * zoom)); + } + + public static void EndZoomed(Rect rect, float zoom) { + GUIUtility.ScaleAroundPivot(Vector2.one * zoom, rect.size * 0.5f); + Vector3 offset = new Vector3( + (((rect.width * zoom) - rect.width) * 0.5f), + (((rect.height * zoom) - rect.height) * 0.5f) + (-22 * zoom)+22, + 0); + GUI.matrix = Matrix4x4.TRS(offset, Quaternion.identity, Vector3.one); + } public static void DrawGrid(Rect rect, float zoom, Vector2 panOffset) { @@ -35,11 +55,11 @@ namespace UNEC { GUI.DrawTextureWithTexCoords(rect, crossTex, new Rect(tileOffset + new Vector2(0.5f,0.5f), tileAmount)); } - public static void DrawToolbar() { + public static void DrawToolbar(NodeEditorWindow window) { EditorGUILayout.BeginHorizontal("Toolbar"); if (DropdownButton("File", 50)) FileContextMenu(); - if (DropdownButton("Edit", 50)) EditContextMenu(); + if (DropdownButton("Edit", 50)) EditContextMenu(window); if (DropdownButton("View", 50)) { } if (DropdownButton("Settings", 70)) { } if (DropdownButton("Tools", 50)) { } @@ -54,16 +74,22 @@ namespace UNEC { return GUILayout.Button(name, EditorStyles.toolbarDropDown, GUILayout.Width(width)); } - public static void RightClickContextMenu() { + public static void RightClickContextMenu(NodeEditorWindow window) { GenericMenu contextMenu = new GenericMenu(); - Vector2 pos = window.GetMousePositionOnGrid(); - for (int i = 0; i < NodeEditorReflection.nodeTypes.Length; i++) { - Type type = NodeEditorReflection.nodeTypes[i]; - contextMenu.AddItem(new GUIContent(NodeEditorReflection.nodeTypes[i].ToString()), false, () => { - NodeEditorAction.CreateNode(type, pos); - }); - } + if (window.hoveredNode != null) { + Node node = window.hoveredNode; + contextMenu.AddItem(new GUIContent("Remove"), false, () => window.graph.RemoveNode(node)); + } + else { + Vector2 pos = window.WindowToGridPosition(Event.current.mousePosition); + for (int i = 0; i < NodeEditorReflection.nodeTypes.Length; i++) { + Type type = NodeEditorReflection.nodeTypes[i]; + contextMenu.AddItem(new GUIContent(NodeEditorReflection.nodeTypes[i].ToString()), false, () => { + window.CreateNode(type, pos); + }); + } + } contextMenu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); } @@ -79,9 +105,9 @@ namespace UNEC { contextMenu.DropDown(new Rect(5f, 17f, 0f, 0f)); } - public static void EditContextMenu() { + public static void EditContextMenu(NodeEditorWindow window) { GenericMenu contextMenu = new GenericMenu(); - contextMenu.AddItem(new GUIContent("Clear"), false, () => window.currentGraph.Clear()); + contextMenu.AddItem(new GUIContent("Clear"), false, () => window.graph.Clear()); contextMenu.DropDown(new Rect(5f, 17f, 0f, 0f)); } diff --git a/Scripts/Editor/NodeEditorWindow.cs b/Scripts/Editor/NodeEditorWindow.cs index c8304b1..75bc975 100644 --- a/Scripts/Editor/NodeEditorWindow.cs +++ b/Scripts/Editor/NodeEditorWindow.cs @@ -6,11 +6,11 @@ using UNEC; public class NodeEditorWindow : EditorWindow { + public NodeGraph graph { get { return _graph != null ? _graph : _graph = new NodeGraph(); } } + public NodeGraph _graph; + public Node hoveredNode; + public Node activeNode { get; private set; } - public static NodeEditorWindow window { get { return focusedWindow as NodeEditorWindow; } } - - public NodeGraph currentGraph { get { return _currentGraph != null ? _currentGraph : _currentGraph = new NodeGraph(); }} - public NodeGraph _currentGraph; public Vector2 panOffset { get { return _panOffset; } set { _panOffset = value; Repaint(); } } private Vector2 _panOffset; public float zoom { get { return _zoom; } set { _zoom = Mathf.Clamp(value, 1f, 5f); Repaint(); } } @@ -25,56 +25,70 @@ public class NodeEditorWindow : EditorWindow { } private void OnGUI() { - NodeEditorAction.Controls(); + Matrix4x4 m = GUI.matrix; + NodeEditorAction.Controls(this); - BeginWindows(); NodeEditorGUI.DrawGrid(position, zoom, panOffset); - NodeEditorGUI.DrawToolbar(); DrawNodes(); - EndWindows(); + NodeEditorGUI.DrawToolbar(this); + GUI.matrix = m; } private void DrawNodes() { - Matrix4x4 m = GUI.matrix; - GUI.EndClip(); - GUIUtility.ScaleAroundPivot(Vector2.one / zoom, position.size * 0.5f); - foreach (KeyValuePair kvp in currentGraph.nodes) { + BeginWindows(); + NodeEditorGUI.BeginZoomed(position, zoom); + Event e = Event.current; + hoveredNode = null; + foreach (KeyValuePair kvp in graph.nodes) { Node node = kvp.Value; + int id = kvp.Key; - //Vector2 p = node.position.position + (position.size *0.5f) + panOffset; //Get node position - Vector2 windowPos = GridToWindowPosition(node.position.position); - windowPos = -windowPos; + Vector2 windowPos = GridToWindowPositionNoClipped(node.position.position); + + Rect windowRect = new Rect(windowPos, new Vector2(200, 200)); + if (windowRect.Contains(e.mousePosition)) hoveredNode = node; + + GUIStyle style = (node == activeNode) ? (GUIStyle)"flow node 0 on" : (GUIStyle)"flow node 0"; + GUI.Box(windowRect, node.ToString(), style); + + + if (windowRect.position != windowPos) { + windowPos = windowRect.position; + node.position.position = WindowToGridPosition(windowPos); + //Vector2 newPos = windowRect = + } - Rect windowRect = new Rect(windowPos, new Vector2(200,200)); - windowRect = GUI.Window(0, windowRect, DraggableWindow, node.ToString()); - //node.position = windowRect.position; } - GUI.matrix = m; - Vector2 padding = new Vector2(0, 0); - padding *= zoom; - GUI.BeginClip(new Rect( - -(((position.width*zoom) - position.width)*0.5f) + (padding.x), - -(((position.height * zoom) - position.height) * 0.5f) + (padding.y), - (position.width*zoom)- (padding.x * 2), - (position.height * zoom) - (padding.y * 2))); + NodeEditorGUI.EndZoomed(position, zoom); + EndWindows(); } private void DraggableWindow(int windowID) { - GUI.DragWindow(new Rect(0, 0, 10000, 20)); - } + GUI.DragWindow(); - public Vector2 GetMousePositionOnGrid() { - return WindowToGridPosition(Event.current.mousePosition); + if (GUILayout.Button("ASDF")) Debug.Log("ASDF"); + if (GUI.Button(new Rect(20,20,200,200),"ASDF")) Debug.Log("ASDF"); } public Vector2 WindowToGridPosition(Vector2 windowPosition) { - return windowPosition - (window.position.size * 0.5f) - (panOffset * zoom); + return (windowPosition - (position.size * 0.5f) - (panOffset / zoom)) * zoom; } public Vector2 GridToWindowPosition(Vector2 gridPosition) { - return ((window.position.size * 0.5f) - (panOffset * zoom)) + gridPosition; + return (position.size * 0.5f) + (panOffset / zoom) + gridPosition; + } + + public Vector2 GridToWindowPositionNoClipped(Vector2 gridPosition) { + Vector2 center = position.size * 0.5f; + float xOffset = (center.x * zoom + (panOffset.x + gridPosition.x)); + float yOffset = (center.y * zoom + (panOffset.y + gridPosition.y)); + return new Vector2(xOffset, yOffset); + } + + public void SelectNode(Node node) { + activeNode = node; } } \ No newline at end of file diff --git a/Scripts/NodeGraph.cs b/Scripts/NodeGraph.cs index b42c2d1..d902fb7 100644 --- a/Scripts/NodeGraph.cs +++ b/Scripts/NodeGraph.cs @@ -6,25 +6,47 @@ using System; /// Base class for all node graphs public class NodeGraph { - public Dictionary nodes = new Dictionary(); + public Dictionary nodes = new Dictionary(); public T AddNode() where T : Node { T node = default(T); - nodes.Add(GetGUID(), node); + nodes.Add(GetUniqueID(), node); return node; } public Node AddNode(Type type) { Node node = (Node)Activator.CreateInstance(type); if (node == null) return null; - nodes.Add(GetGUID(), node); + nodes.Add(GetUniqueID(), node); return node; } - private string GetGUID() { - string guid = Guid.NewGuid().ToString(); - while(nodes.ContainsKey(guid)) guid = GetGUID(); - return guid; + public void RemoveNode(Node node) { + int id = GetNodeID(node); + if (id != -1) nodes.Remove(id); + else Debug.LogWarning("Node " + node.ToString() + " is not part of NodeGraph"); + } + + public void RemoveNode(int id) { + nodes.Remove(id); + } + + public int GetNodeID(Node node) { + foreach(var kvp in nodes) { + if (kvp.Value == node) return kvp.Key; + } + return -1; + } + + public Node GetNode(int id) { + if (nodes.ContainsKey(id)) return nodes[id]; + return null; + } + + private int GetUniqueID() { + int id = 0; + while (nodes.ContainsKey(id)) id++; + return id; } public void Clear() {