private static void KeyDupe(NodeEditorInputInfo inputInfo) { inputInfo.SetAsCurrentEnvironment(); NodeEditorState state = inputInfo.editorState; if (state.focusedNode != null) { // Create new node of same type Node duplicatedNode = Node.Create(state.focusedNode.GetID, NodeEditor.ScreenToCanvasSpace(inputInfo.inputPos), state.connectOutput); state.selectedNode = state.focusedNode = duplicatedNode; state.connectOutput = null; inputInfo.inputEvent.Use(); } }
public static Node Create(string nodeID, Vector2 position, NodeOutput connectingOutput) { Node defaultNode = NodeTypes.getDefaultNode(nodeID); if ((UnityEngine.Object)defaultNode == (UnityEngine.Object)null) { throw new UnityException("Cannot create Node with id " + nodeID + " as no such Node type is registered!"); } defaultNode = defaultNode.Create(position); defaultNode.InitBase(); if ((UnityEngine.Object)connectingOutput != (UnityEngine.Object)null) { foreach (NodeInput input in defaultNode.Inputs) { if (input.TryApplyConnection(connectingOutput)) { break; } } } NodeEditorCallbacks.IssueOnAddNode(defaultNode); return(defaultNode); }
/// <summary> /// Fetches every Node Declaration in the assembly and stores them in the nodes List. /// nodes List contains a default instance of each node type in the key and editor specific NodeData in the value /// </summary> public static void FetchNodes() { nodes = new Dictionary <Node, NodeData> (); IEnumerable <Assembly> scriptAssemblies = AppDomain.CurrentDomain.GetAssemblies().Where((Assembly assembly) => assembly.FullName.Contains("Assembly")); foreach (Assembly assembly in scriptAssemblies) { foreach (Type type in assembly.GetTypes().Where(T => T.IsClass && !T.IsAbstract && T.IsSubclassOf(typeof(Node)))) { object[] nodeAttributes = type.GetCustomAttributes(typeof(NodeAttribute), false); NodeAttribute attr = nodeAttributes[0] as NodeAttribute; if (attr == null || !attr.hide) { Node node = ScriptableObject.CreateInstance(type.Name) as Node; // Create a 'raw' instance (not setup using the appropriate Create function) node = node.Create(Vector2.zero); // From that, call the appropriate Create Method to init the previously 'raw' instance nodes.Add(node, new NodeData(attr == null ? node.name : attr.contextText, attr.typeOfNodeCanvas)); } } } }
public static void DuplicateNodeOrNodes(NodeEditorInputInfo inputInfo) { if (inputInfo.editorState.selectedNode == null && NodeEditor.curEditorState.selectedNodes.Count == 0) { return; } inputInfo.SetAsCurrentEnvironment(); NodeEditorState state = inputInfo.editorState; if (inputInfo.editorState.selectedNode != null && !NodeEditor.curEditorState.selectedNodes.Contains(inputInfo.editorState.selectedNode)) { NodeEditor.curEditorState.selectedNodes.Add(inputInfo.editorState.selectedNode); } { // if(m_CacheOff!=null) // m_CacheOff(); Dictionary <Node, Node> nodeMap = new Dictionary <Node, Node>(); List <Node> newSelected = new List <Node>(); foreach (var n in NodeEditor.curEditorState.selectedNodes) { Node duplicated = Node.Create(n.GetID, n.rect.center, null, false); //state.connectOutput); // Debug.Log("dupe n "+n); duplicated.CloneFieldsFrom(n); state.selectedNode = state.focusedNode = duplicated; newSelected.Add(duplicated); nodeMap.Add(n, duplicated); } //handle connections foreach (var n in NodeEditor.curEditorState.selectedNodes) { for (int index = 0; index < n.Inputs.Count; index++) { NodeInput nodeInput = n.Inputs[index]; if (nodeInput.connection != null) { Node connectTo = nodeInput.connection.body; if (nodeMap.ContainsKey(nodeInput.connection.body)) { connectTo = nodeMap[nodeInput.connection.body]; } foreach (NodeOutput on in connectTo.Outputs) { if (on.name == nodeInput.connection.name) { if (index < nodeMap[n].Inputs.Count) { nodeMap[n].Inputs[index].ApplyConnection(on); } break; } } } } for (int index = 0; index < n.Outputs.Count; index++) { NodeOutput nodeOutput = n.Outputs[index]; for (int index1 = 0; index1 < nodeOutput.connections.Count; index1++) { NodeInput nodeInput = nodeOutput.connections[index1]; if (nodeInput == null) { continue; } Node connectTo = nodeInput.body; if (nodeMap.ContainsKey(connectTo)) { continue; //we did it allready } for (int i = 0; i < connectTo.Inputs.Count; i++) { NodeInput inputnode = connectTo.Inputs[i]; if (inputnode.name == nodeInput.name) { inputnode.ApplyConnection(nodeOutput); break; } } } } } NodeEditor.curEditorState.selectedNodes.Clear(); NodeEditor.curEditorState.selectedNodes = newSelected; NodeEditor.curEditorState.selectedNode = newSelected[0]; // foreach (var x in newSelected) // Debug.Log(" selected node "+x); // if (m_CacheOn != null) // m_CacheOn(); NodeEditorCallbacks.IssueOnAddNode(NodeEditor.curEditorState.selectedNode); //just do it on one node, so it saves the canvas/repaints } state.connectOutput = null; if (m_FinishedDupe != null) { m_FinishedDupe(); } }
[EventHandlerAttribute(EventType.DragPerform, 90)] // Priority over hundred to make it call after the GUI private static void HandleDragAndDrop(NodeEditorInputInfo inputInfo) { if (inputInfo.inputEvent.type == EventType.DragUpdated || (inputInfo.inputEvent.type == EventType.DragPerform)) { //Debug.LogError("handle drag " + inputInfo.inputEvent.type); DragAndDrop.visualMode = DragAndDropVisualMode.Copy; if (inputInfo.inputEvent.type == EventType.DragPerform && DragAndDrop.objectReferences.Length > 0 && (DragAndDrop.objectReferences[0] is Texture2D)) { Debug.Log(" drag texture " + DragAndDrop.objectReferences[0]); UnityTextureInput node = (UnityTextureInput) Node.Create("UnityTextureInput", NodeEditor.ScreenToCanvasSpace(inputInfo.inputPos)); node.m_Input = DragAndDrop.objectReferences[0] as Texture2D; inputInfo.inputEvent.Use(); } else if (inputInfo.inputEvent.type == EventType.DragPerform && DragAndDrop.GetGenericData("GenericDragColumnDragging") != null) { DragAndDrop.AcceptDrag(); //Debug.Log("dragged generic data "+ DragAndDrop.GetGenericData("GenericDragColumnDragging")); List <UnityEditor.IMGUI.Controls.TreeViewItem> _data = DragAndDrop.GetGenericData("GenericDragColumnDragging") as List <UnityEditor.IMGUI.Controls.TreeViewItem>; var draggedElements = new List <TreeElement>(); foreach (var x in _data) { draggedElements.Add(((TreeViewItem <MyTreeElement>)x).data); } var srcItem = draggedElements[0] as MyTreeElement; if (srcItem.m_Canvas) { SubTreeNode node = (SubTreeNode) Node.Create("SubTreeNode", NodeEditor.ScreenToCanvasSpace(inputInfo.inputPos)); node.SubCanvas = srcItem.m_Canvas; string assetPath = AssetDatabase.GetAssetPath(node.SubCanvas); // Debug.Log("drag and drop asset canvas path >" + assetPath + "<"); if (assetPath.Length > 0) { node.m_CanvasGuid = AssetDatabase.AssetPathToGUID(assetPath); Debug.LogError(" set canvasGuid from asset >" + node.m_CanvasGuid + "<"); string fname = Path.GetFileName(assetPath); fname = Path.ChangeExtension(fname, ""); node.name = "Sub:" + fname; } node.OnLoadCanvas(); } else { Node node = Node.Create(srcItem.m_NodeID, NodeEditor.ScreenToCanvasSpace(inputInfo.inputPos)); } inputInfo.inputEvent.Use(); } else if (inputInfo.inputEvent.type == EventType.DragPerform && DragAndDrop.objectReferences.Length > 0 && (DragAndDrop.objectReferences[0] is NodeCanvas)) { DragAndDrop.AcceptDrag(); // Debug.Log(" drag and drop " + DragAndDrop.objectReferences[0] + " co ord " + Event.current.mousePosition); SubTreeNode node = (SubTreeNode) Node.Create("SubTreeNode", NodeEditor.ScreenToCanvasSpace(inputInfo.inputPos)); node.SubCanvas = (NodeCanvas)DragAndDrop.objectReferences[0]; string assetPath = AssetDatabase.GetAssetPath(node.SubCanvas); // Debug.Log("drag and drop asset canvas path >" + assetPath + "<"); if (assetPath.Length > 0) { node.m_CanvasGuid = AssetDatabase.AssetPathToGUID(assetPath); Debug.LogError(" set canvasGuid from asset >" + node.m_CanvasGuid + "<"); string fname = Path.GetFileName(assetPath); fname = Path.ChangeExtension(fname, ""); node.name = "Sub:" + fname; } inputInfo.inputEvent.Use(); node.OnLoadCanvas(); } } }
/// <summary> /// Context Click selection. Here you'll need to register your own using a string identifier /// </summary> public static void ContextCallback(object obj) { callbackObject cbObj = obj as callbackObject; curNodeCanvas = cbObj.canvas; curEditorState = cbObj.editor; switch (cbObj.message) { case "deleteNode": if (curEditorState.focusedNode != null) { curEditorState.focusedNode.Delete(); } break; case "duplicateNode": if (curEditorState.focusedNode != null) { ContextCallback(new callbackObject(curEditorState.focusedNode.GetID, curNodeCanvas, curEditorState)); Node duplicatedNode = curNodeCanvas.nodes [curNodeCanvas.nodes.Count - 1]; curEditorState.focusedNode = duplicatedNode; curEditorState.dragNode = true; curEditorState.makeTransition = null; curEditorState.connectOutput = null; curEditorState.panWindow = false; } break; case "startTransition": if (curEditorState.focusedNode != null) { curEditorState.makeTransition = curEditorState.focusedNode; curEditorState.connectOutput = null; } curEditorState.dragNode = false; curEditorState.panWindow = false; break; default: Vector2 createPos = ScreenToGUIPos(mousePos); Node node = NodeTypes.getDefaultNode(cbObj.message); if (node == null) { break; } bool acceptTransitions = NodeTypes.nodes [node].transitions; node = node.Create(createPos); node.InitBase(); NodeEditorCallbacks.IssueOnAddNode(node); if (curEditorState.connectOutput != null) { // If nodeOutput is defined, link it to the first input of the same type foreach (NodeInput input in node.Inputs) { if (Node.CanApplyConnection(curEditorState.connectOutput, input)) { // If it can connect (type is equals, it does not cause recursion, ...) Node.ApplyConnection(curEditorState.connectOutput, input); break; } } } else if (acceptTransitions && curEditorState.makeTransition != null) { Node.CreateTransition(curEditorState.makeTransition, node); } curEditorState.makeTransition = null; curEditorState.connectOutput = null; curEditorState.dragNode = false; curEditorState.panWindow = false; break; } if (NodeEditor.Repaint != null) { NodeEditor.Repaint(); } }
/// <summary> /// Evaluates context callbacks previously registered /// </summary> public static void ContextCallback(object obj) { NodeEditorMenuCallback callback = obj as NodeEditorMenuCallback; if (callback == null) { throw new UnityException("Callback Object passed by context is not of type NodeEditorMenuCallback!"); } curNodeCanvas = callback.canvas; curEditorState = callback.editor; switch (callback.message) { case "deleteNode": // Delete request if (curEditorState.focusedNode != null) { curEditorState.focusedNode.Delete(); } break; case "duplicateNode": // Duplicate request if (curEditorState.focusedNode != null) { ContextCallback(new NodeEditorMenuCallback(curEditorState.focusedNode.GetID, curNodeCanvas, curEditorState)); Node duplicatedNode = curNodeCanvas.nodes [curNodeCanvas.nodes.Count - 1]; curEditorState.focusedNode = duplicatedNode; curEditorState.dragNode = true; curEditorState.makeTransition = null; curEditorState.connectOutput = null; curEditorState.panWindow = false; } break; case "startTransition": // Starting a new transition if (curEditorState.focusedNode != null) { curEditorState.makeTransition = curEditorState.focusedNode; curEditorState.connectOutput = null; } curEditorState.dragNode = false; curEditorState.panWindow = false; break; default: // Node creation request Node node = Node.Create(callback.message, ScreenToGUIPos(callback.contextClickPos)); // Handle auto-connection if (curEditorState.connectOutput != null) { // If nodeOutput is defined, link it to the first input of the same type foreach (NodeInput input in node.Inputs) { if (input.CanApplyConnection(curEditorState.connectOutput)) { // If it can connect (type is equals, it does not cause recursion, ...) input.ApplyConnection(curEditorState.connectOutput); break; } } } curEditorState.makeTransition = null; curEditorState.connectOutput = null; curEditorState.dragNode = false; curEditorState.panWindow = false; break; } RepaintClients(); }