/// <summary> /// Sets the value. /// </summary> public void SetValue <T> (T Value) { if (valueType == null) { valueType = ConnectionTypes.GetType(type); } if (valueType == typeof(T)) { value = Value; } else { Debug.LogError("Trying to SetValue<" + typeof(T).FullName + "> for Output Type: " + valueType.FullName); } }
private void CheckType() { if (_typeData == null || !_typeData.isValid()) { _typeData = ConnectionTypes.GetTypeData(typeID); } if (_typeData == null || !_typeData.isValid()) { ConnectionTypes.FetchTypes(); _typeData = ConnectionTypes.GetTypeData(typeID); if (_typeData == null || !_typeData.isValid()) { throw new UnityException("Could not find type " + typeID + "!"); } } }
/// <summary> /// Gets the output value. /// </summary> /// <returns>Value, if null default(T) (-> For reference types, null. For value types, default value)</returns> public T GetValue <T> () { if (valueType == null) { valueType = ConnectionTypes.GetType(type); } if (valueType == typeof(T)) { if (value == null) { value = getDefault <T> (); } return((T)value); } Debug.LogError("Trying to GetValue<" + typeof(T).FullName + "> for Output Type: " + valueType.FullName); return(getDefault <T> ()); }
/// <summary> /// Draws the node curves; splitted from knobs because of the render order /// </summary> protected internal virtual void DrawConnections() { for (int outCnt = 0; outCnt < Outputs.Count; outCnt++) { NodeOutput output = Outputs [outCnt]; Vector2 startPos = output.GetGUIKnob().center; Vector2 startDir = output.GetDirection(); for (int conCnt = 0; conCnt < output.connections.Count; conCnt++) { NodeInput input = output.connections [conCnt]; NodeEditorGUI.DrawConnection(startPos, startDir, input.GetGUIKnob().center, input.GetDirection(), ConnectionTypes.GetTypeData(output.type).col); } } }
public static void ReInit(bool GUIFunction) { CheckEditorPath(); ResourceManager.SetDefaultResourcePath(editorPath + "Resources/"); if (!NodeEditorGUI.Init(GUIFunction)) { InitiationError = true; } else { ConnectionTypes.FetchTypes(); NodeTypes.FetchNodes(); NodeCanvasManager.GetAllCanvasTypes(); NodeEditorCallbacks.SetupReceivers(); NodeEditorCallbacks.IssueOnEditorStartUp(); GUIScaleUtility.CheckInit(); NodeEditorInputSystem.SetupInput(); initiated = GUIFunction; } }
/// <summary> /// Draws the node curves /// </summary> protected internal virtual void DrawConnections() { CheckNodeKnobMigration(); if (Event.current.type != EventType.Repaint) { return; } foreach (NodeOutput output in Outputs) { Vector2 startPos = output.GetGUIKnob().center; Vector2 startDir = output.GetDirection(); foreach (NodeInput input in output.connections) { NodeEditorGUI.DrawConnection(startPos, startDir, input.GetGUIKnob().center, input.GetDirection(), ConnectionTypes.GetTypeData(output.type, true).Color); } } }
/// <summary> /// Re-Inits the NodeCanvas regardless of whetehr it was initiated before /// </summary> public static void ReInit(bool GUIFunction) { CheckEditorPath(); // Init Resource system. Can be called anywhere else, too, if it's needed before. ResourceManager.SetDefaultResourcePath(editorPath + "Resources/"); // Init NE GUI. I may throw an error if a texture was not found. if (!NodeEditorGUI.Init(GUIFunction)) { InitiationError = true; return; } // Run fetching algorithms searching the script assemblies for Custom Nodes / Connection Types ConnectionTypes.FetchTypes(); NodeTypes.FetchNodes(); NodeCanvasManager.GetAllCanvasTypes(); // Setup Callback system NodeEditorCallbacks.SetupReceivers(); NodeEditorCallbacks.IssueOnEditorStartUp(); // Init GUIScaleUtility. This fetches reflected calls and my throw a message notifying about incompability. GUIScaleUtility.CheckInit(); // Init input NodeEditorInputSystem.SetupInput(); #if UNITY_EDITOR UnityEditor.EditorApplication.update -= Update; UnityEditor.EditorApplication.update += Update; RepaintClients(); #endif initiated = GUIFunction; }
public void CheckTexture() { if (knobTexture == null) { knobTexture = ConnectionTypes.GetTypeData(type).InputKnob; if (knobTexture == null) { throw new UnityException("Connection type " + type + " has no knob texture assigned!"); } if (side != NodeSide.Left) { int cur = (int)NodeSide.Left, next = (int)side; if (next < cur) { next += 4; } while (cur < next) { knobTexture = NodeEditorGUI.RotateTexture90Degrees(knobTexture); cur++; } } } }
/// <summary> /// Draws the node curves /// </summary> protected internal virtual void DrawConnections() { CheckNodeKnobMigration(); if (Event.current.type != EventType.Repaint) { return; } for (int outCnt = 0; outCnt < Outputs.Count; outCnt++) { NodeOutput output = Outputs [outCnt]; Vector2 startPos = output.GetGUIKnob().center; Vector2 startDir = output.GetDirection(); for (int conCnt = 0; conCnt < output.connections.Count; conCnt++) { NodeInput input = output.connections [conCnt]; NodeEditorGUI.DrawConnection(startPos, startDir, input.GetGUIKnob().center, input.GetDirection(), ConnectionTypes.GetTypeData(output.type).col); } } }
/// <summary> /// Draws the Node Canvas on the screen in the rect specified by editorState /// </summary> public static void DrawSubCanvas(NodeCanvas nodeCanvas, NodeEditorState editorState) { if (!editorState.drawing) { return; } NodeCanvas prevNodeCanvas = curNodeCanvas; NodeEditorState prevEditorState = curEditorState; curNodeCanvas = nodeCanvas; curEditorState = editorState; if (Event.current.type == EventType.Repaint) { // Draw Background when Repainting GUI.BeginClip(curEditorState.canvasRect); float width = NodeEditorGUI.Background.width / curEditorState.zoom; float height = NodeEditorGUI.Background.height / curEditorState.zoom; Vector2 offset = new Vector2((curEditorState.panOffset.x / curEditorState.zoom) % width - width, (curEditorState.panOffset.y / curEditorState.zoom) % height - height); int tileX = Mathf.CeilToInt((curEditorState.canvasRect.width + (width - offset.x)) / width); int tileY = Mathf.CeilToInt((curEditorState.canvasRect.height + (height - offset.y)) / height); for (int x = 0; x < tileX; x++) { for (int y = 0; y < tileY; y++) { Rect texRect = new Rect(offset.x + x * width, offset.y + y * height, width, height); GUI.DrawTexture(texRect, NodeEditorGUI.Background); } } GUI.EndClip(); } // Check the inputs InputEvents(curEditorState.ignoreInput); curEditorState.ignoreInput = new List <Rect> (); // We're using a custom scale methode, as default one is messing up clipping rect Rect canvasRect = curEditorState.canvasRect; curEditorState.zoomPanAdjust = GUIScaleUtility.BeginScale(ref canvasRect, curEditorState.zoomPos, curEditorState.zoom, true); //GUILayout.Label ("Scaling is Great!"); -> Test by changin the last bool parameter // ---- BEGIN SCALE ---- // Some features which require drawing (zoomed) if (curEditorState.navigate) { // Draw a curve to the origin/active node for orientation purposes NodeEditorGUI.DrawLine(curEditorState.activeNode != null? curEditorState.activeNode.rect.center + curEditorState.zoomPanAdjust : curEditorState.panOffset, ScreenToGUIPos(mousePos) + curEditorState.zoomPos * curEditorState.zoom, Color.black, null, 3); if (Repaint != null) { Repaint(); } } if (curEditorState.connectOutput != null) { // Draw the currently drawn connection NodeOutput output = curEditorState.connectOutput; DrawConnection(output.GetGUIKnob().center, output.GetDirection(), ScreenToGUIPos(mousePos) + curEditorState.zoomPos * curEditorState.zoom, Vector2.right, ConnectionTypes.GetTypeData(output.type).col); if (Repaint != null) { Repaint(); } } if (curEditorState.makeTransition != null) { // Draw the currently made transition NodeEditorGUI.DrawLine(curEditorState.makeTransition.rect.center + curEditorState.zoomPanAdjust, ScreenToGUIPos(mousePos) + curEditorState.zoomPos * curEditorState.zoom, Color.grey, null, 3); if (Repaint != null) { Repaint(); } } // Push the active cell at the bottom of the draw order. if (Event.current.type == EventType.Layout && curEditorState.activeNode != null) { curNodeCanvas.nodes.Remove(curEditorState.activeNode); curNodeCanvas.nodes.Add(curEditorState.activeNode); } // Draw the transitions. Has to be called before nodes as transitions originate from node centers for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { curNodeCanvas.nodes [nodeCnt].DrawTransitions(); } for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { curNodeCanvas.nodes [nodeCnt].DrawConnections(); } // Draw the nodes for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { curNodeCanvas.nodes [nodeCnt].DrawNode(); curNodeCanvas.nodes [nodeCnt].DrawKnobs(); } // ---- END SCALE ---- // End scaling group GUIScaleUtility.EndScale(); // Check events with less priority than node GUI controls LateEvents(curEditorState.ignoreInput); curNodeCanvas = prevNodeCanvas; curEditorState = prevEditorState; }
/// <summary> /// Draws the Node Canvas on the screen in the rect specified by editorState. Has to be called out of any GUI Group or area because of zooming. /// </summary> public static void DrawCanvas(NodeCanvas nodeCanvas, NodeEditorState editorState, Action repaint) { if (!editorState.drawing) { return; } curNodeCanvas = nodeCanvas; curEditorState = editorState; if (repaint != null) { Repaint += repaint; } // if (curEditorState.parent != null) // curEditorState.canvasRect.position += curEditorState.parent.zoomPanAdjust; if (Event.current.type == EventType.Repaint) { // Draw Background when Repainting GUI.BeginClip(curEditorState.canvasRect); float width = Background.width / curEditorState.zoom; float height = Background.height / curEditorState.zoom; Vector2 offset = new Vector2((curEditorState.panOffset.x / curEditorState.zoom) % width - width, (curEditorState.panOffset.y / curEditorState.zoom) % height - height); int tileX = Mathf.CeilToInt((curEditorState.canvasRect.width + (width - offset.x)) / width); int tileY = Mathf.CeilToInt((curEditorState.canvasRect.height + (height - offset.y)) / height); for (int x = 0; x < tileX; x++) { for (int y = 0; y < tileY; y++) { Rect texRect = new Rect(offset.x + x * width, offset.y + y * height, width, height); GUI.DrawTexture(texRect, Background); } } GUI.EndClip(); } // if (curEditorState.parent != null) // curEditorState.canvasRect.position -= curEditorState.parent.zoomPanAdjust - curEditorState.parent.zoomPos; // Fetch all nested nodeEditors and set their canvasRects to be ignored by input, // so it can be handled later, and note it down, as it will be drawn later ontop List <Rect> ignoreInput = new List <Rect> (); for (int childCnt = 0; childCnt < curEditorState.childs.Count; childCnt++) { if (curEditorState.childs [childCnt].drawing) { NodeEditorState nestedEditor = curEditorState.childs [childCnt]; ignoreInput.Add(GUIToScreenRect(nestedEditor.canvasRect)); } } // Check the inputs InputEvents(ignoreInput); // We want to scale our nodes, but as GUI.matrix also scales our widnow's clipping group, // we have to scale it up first to receive a correct one as a result #region Scale Setup // End the default clipping group GUI.EndGroup(); // The Rect of the new clipping group to draw our nodes in Rect ScaledCanvasRect = ScaleRect(curEditorState.canvasRect, curEditorState.zoomPos + curEditorState.canvasRect.position, new Vector2(curEditorState.zoom, curEditorState.zoom)); ScaledCanvasRect.y += 23; // Header tab height if (curNodeCanvas != NodeEditorWindow.MainNodeCanvas) { GUI.DrawTexture(ScaledCanvasRect, Background); } // Now continue drawing using the new clipping group GUI.BeginGroup(ScaledCanvasRect); ScaledCanvasRect.position = Vector2.zero; // Adjust because we entered the new group // Because I currently found no way to actually scale to the center of the window rather than (0, 0), // I'm going to cheat and just pan it accordingly to let it appear as if it would scroll to the center // Note, due to that, other controls are still scaled to (0, 0) curEditorState.zoomPanAdjust = ScaledCanvasRect.center - curEditorState.canvasRect.size / 2 + curEditorState.zoomPos; // Take a matrix backup to restore back later on Matrix4x4 GUIMatrix = GUI.matrix; // Scale GUI.matrix. After that we have the correct clipping group again. GUIUtility.ScaleAroundPivot(new Vector2(1 / curEditorState.zoom, 1 / curEditorState.zoom), curEditorState.zoomPanAdjust); #endregion // Some features which require drawing (zoomed) if (curEditorState.navigate) { // Draw a curve to the origin/active node for orientation purposes DrawLine(curEditorState.activeNode != null? curEditorState.activeNode.rect.center + curEditorState.zoomPanAdjust : curEditorState.panOffset, ScreenToGUIPos(mousePos) + curEditorState.zoomPos * curEditorState.zoom, Color.black, null, 3); if (Repaint != null) { Repaint(); } } if (curEditorState.connectOutput != null) { // Draw the currently drawn connection DrawConnection(curEditorState.connectOutput.GetGUIKnob().center, ScreenToGUIPos(mousePos) + curEditorState.zoomPos * curEditorState.zoom, ConnectionTypes.GetTypeData(curEditorState.connectOutput.type).col); if (Repaint != null) { Repaint(); } } if (curEditorState.makeTransition != null) { // Draw the currently made transition DrawLine(curEditorState.makeTransition.rect.center + curEditorState.zoomPanAdjust, ScreenToGUIPos(mousePos) + curEditorState.zoomPos * curEditorState.zoom, Color.grey, null, 3); if (Repaint != null) { Repaint(); } } // Draw the Node connectors; Seperated because of render order for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { curNodeCanvas.nodes [nodeCnt].DrawConnections(); } for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { curNodeCanvas.nodes [nodeCnt].DrawKnobs(); } for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { curNodeCanvas.nodes [nodeCnt].DrawTransitions(); } // Draw the nodes for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { Node node = curNodeCanvas.nodes [nodeCnt]; //if (node != curEditorState.activeNode) NodeEditor.DrawNode(node); } // Draw the active Node ontop // if (editorState.activeNode != null) // NodeEditor.DrawNode (curEditorState.activeNode); // Draw any node groups out there. Has to be drawn here, because they still need to scale according to their parents, but they mustn't be drawn inside a GUI group for (int editorCnt = 0; editorCnt < curEditorState.childs.Count; editorCnt++) { if (curEditorState.childs [editorCnt].drawing) { NodeEditorState nestedEditor = curEditorState.childs [editorCnt]; nestedEditor.canvasRect.position += curEditorState.zoomPanAdjust; //GUI.DrawTexture (nestedEditor.canvasRect, Background); DrawCanvas(nestedEditor.canvas, nestedEditor, Repaint); nestedEditor.canvasRect.position -= curEditorState.zoomPanAdjust; } } curNodeCanvas = nodeCanvas; curEditorState = editorState; // End scaling group // Set default matrix and clipping group for the rest GUI.matrix = GUIMatrix; GUI.EndGroup(); if (curNodeCanvas.parent == null) { GUI.BeginGroup(new Rect(0, 23, NodeEditorWindow.editor.position.width, NodeEditorWindow.editor.position.height)); } else { Rect parentGroupRect = ScaleRect(curEditorState.parent.canvasRect, curEditorState.parent.zoomPos + curEditorState.parent.canvasRect.position, new Vector2(curEditorState.parent.zoom, curEditorState.parent.zoom)); parentGroupRect.y += 23; // Header tab height GUI.BeginGroup(parentGroupRect); } // Check events with less priority than node GUI controls LateEvents(ignoreInput); }
/// <summary> /// Draws the Node Canvas on the screen in the rect specified by editorState without one-time wrappers like GUISkin and OverlayGUI. Made for nested Canvases (WIP) /// </summary> public static void DrawSubCanvas(NodeCanvas nodeCanvas, NodeEditorState editorState) { if (!editorState.drawing) { return; } // Store and restore later on in case of this being a nested Canvas NodeCanvas prevNodeCanvas = curNodeCanvas; NodeEditorState prevEditorState = curEditorState; curNodeCanvas = nodeCanvas; curEditorState = editorState; if (Event.current.type == EventType.Repaint) { // Draw Background when Repainting GUI.BeginClip(curEditorState.canvasRect); float width = NodeEditorGUI.Background.width / curEditorState.zoom; float height = NodeEditorGUI.Background.height / curEditorState.zoom; Vector2 offset = curEditorState.zoomPos + curEditorState.panOffset / curEditorState.zoom; offset = new Vector2(offset.x % width - width, offset.y % height - height); int tileX = Mathf.CeilToInt((curEditorState.canvasRect.width + (width - offset.x)) / width); int tileY = Mathf.CeilToInt((curEditorState.canvasRect.height + (height - offset.y)) / height); for (int x = 0; x < tileX; x++) { for (int y = 0; y < tileY; y++) { GUI.DrawTexture(new Rect(offset.x + x * width, offset.y + y * height, width, height), NodeEditorGUI.Background); } } GUI.EndClip(); } // Check the inputs InputEvents(); if (Event.current.type != EventType.Layout) { curEditorState.ignoreInput = new List <Rect> (); } // We're using a custom scale method, as default one is messing up clipping rect Rect canvasRect = curEditorState.canvasRect; curEditorState.zoomPanAdjust = GUIScaleUtility.BeginScale(ref canvasRect, curEditorState.zoomPos, curEditorState.zoom, false); //GUILayout.Label ("Scaling is Great!"); -> TODO: Test by changing the last bool parameter // ---- BEGIN SCALE ---- // Some features which require drawing (zoomed) if (curEditorState.navigate) { // Draw a curve to the origin/active node for orientation purposes RTEditorGUI.DrawLine((curEditorState.selectedNode != null? curEditorState.selectedNode.rect.center : curEditorState.panOffset) + curEditorState.zoomPanAdjust, ScreenToGUIPos(mousePos) + curEditorState.zoomPos * curEditorState.zoom, Color.black, null, 3); RepaintClients(); } if (curEditorState.connectOutput != null) { // Draw the currently drawn connection NodeOutput output = curEditorState.connectOutput; Vector2 startPos = output.GetGUIKnob().center; Vector2 endPos = ScreenToGUIPos(mousePos) + curEditorState.zoomPos * curEditorState.zoom; Vector2 endDir = output.GetDirection(); NodeEditorGUI.DrawConnection(startPos, endDir, endPos, NodeEditorGUI.GetSecondConnectionVector(startPos, endPos, endDir), ConnectionTypes.GetTypeData(output.type, true).Color); RepaintClients(); } if (curEditorState.makeTransition != null) { // Draw the currently made transition RTEditorGUI.DrawLine(curEditorState.makeTransition.rect.center + curEditorState.zoomPanAdjust, ScreenToGUIPos(mousePos) + curEditorState.zoomPos * curEditorState.zoom, Color.grey, null, 3); RepaintClients(); } // Push the active node at the bottom of the draw order. if (Event.current.type == EventType.Layout && curEditorState.selectedNode != null) { curNodeCanvas.nodes.Remove(curEditorState.selectedNode); curNodeCanvas.nodes.Add(curEditorState.selectedNode); } // Draw the transitions and connections. Has to be drawn before nodes as transitions originate from node centers foreach (Node node in curNodeCanvas.nodes) { node.DrawConnections(); } // Draw the nodes foreach (Node node in curNodeCanvas.nodes) { node.DrawNode(); if (Event.current.type == EventType.Repaint) { node.DrawKnobs(); } } // ---- END SCALE ---- // End scaling group GUIScaleUtility.EndScale(); // Check events with less priority than node GUI controls LateEvents(); curNodeCanvas = prevNodeCanvas; curEditorState = prevEditorState; }