Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Simple node editor

Discussion in 'Immediate Mode GUI (IMGUI)' started by unimechanic, Jul 5, 2013.

  1. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Hey dshinigami,
    No stupid questions, the IMGUI system as well as this Node Editor Framework are complex on the first glance.
    I would look into the basics of IMGUI before though as it is heavily used in editor programming in Unity:)

    Also, don't be confused with the RTEditorGUI class, as it's name suggests it contains runtime versions of the editor GUI elements. So if you want your code to work in runtime, you have to make sure to only use editor classes (GUILayout instead of EditorGUILayout) or if you need an editor feature, you can take a look in RTEditorGUI for an alternative. But that shouldn't bother you if you only need an editor.

    There are (semi-)automated GUI drawers for object and their properties, just think of the Inspector displaying your script properties. But if every node of yours has roughly the same structure, this is absolutely unnecessary (after all, it would require to perform alot of reflection calls).

    Regarding your XML-loaded graph, it wouldn't be too complex at a first glance, but contains some more advanced topics in the Node Editor itself which I haven't documented so far.
    I can help you with your question node and how to create complete graphs including auto-layouting and connections/dependencies by code using XML, though:)
    So, given is the raw XML information as you stated. Let's take a similar structure to yours:
    A Node represents a question, and it contains answers leading to more question options each. These can be represented by the NodeOutputs (which are the 'Ports' to connect to other Nodes using 'edges').
    So, the aswers have to be stored parallel/along with these Knobs. Then, the further questions can be accessed by the OutputKnob interface easily.

    On the interface part, you'll likely want to achieve a node where you have nodeKnobs for each answer, and a way to add an answer option, aswell as connecting answer 'responses' (further questions / nodes) through the default Node Editor connecting.
    These are some advanced topics, as you would need to add knobs during edit-time (not just on creation) and you would do alot of creation through code (this doesn't seem too complex, but it is indeed different from the knob creation at node creation time, if you understand what I mean...)

    I have very limited time for the project unfortunately, and I'd really like to help you in more general terms, so I can write up the documentation covering these topics along the way, perhaps writing an 'article' about it.
    You can PM me and I'll try to help you when I have time:)
     
  2. Aishiteru

    Aishiteru

    Joined:
    May 3, 2014
    Posts:
    31
    Hi Seneral, is it possible in the current state of node editor to make additional output knobs in editor run time (not play mode) by a click of a button ? Is there a reason why the reference of node become null in the NodeGUI()

    Code (CSharp):
    1. protected internal override void NodeGUI()
    2.         {
    3.             GUILayout.BeginVertical();
    4.             GUILayout.BeginHorizontal();
    5.             GUILayout.Label("Dialogue");
    6.             if (GUILayout.Button("Add Transition"))
    7.             {
    8.                 node.CreateOutput("Output Right", "Float", NodeSide.Right, 60 + outputCount*20);
    9.                 ++outputCount;
    10.             }
    11.             GUILayout.EndHorizontal();
    12.  
    13.             value = GUILayout.TextArea(value);
    14.            
    15.             GUILayout.EndVertical();  
    16.         }
     
  3. andxet

    andxet

    Joined:
    Jul 8, 2013
    Posts:
    4
    Hi Seneral, thank you for your answer!

    I've decided to do this way: I've created two class who inherites from NodeInput and NodeOuput, respectively PortConnection and NodeConnection. Node connection is simply a NodeOutput without the need to specify the type of connection, setted to custome Node type I've created IConnectionTypeDeclaration. PortConnection have a property, the port who represent, and its instance is created on the overrided Create method. I also overrided the CanApplyConnection,
    ApplyConnection and RemoveConnection adding and removing edges when needed.
    Now I'm testing, and I'm thinking that inherite from NodeInput and NodeOuput was a bad idea because when I save the canvas, when I reload all the PortConnection and NodeConnection are became of type of their base class.

    Now I think to make them extend the NodeKnob class and create on the Node class the needed Lists other that Inputs and Ouputs. Maybe I can find a way to make the creation of that list transparent, so it can be possible to create connections with arbitrary type.

    About the adding and deleting knobs during edit-time, I created the method Destroy on the NodeEditorFramework.Node class, removing connections and removing the NodeInput from the Inputs list.

    I'll think about the editor in the future, only when the part about connections is running. I was thinking to edit the ports from the Nodes, edit the edges clicking from the lines and so on. However, I don't need to use the node editor in runtime, but in the unity editor only.

    EDIT:
    I've red right now how works ScriptableObjects. I don't really need to save to an .asset file my graph, and I already have a function to serialize in xml. So I think that I'll change the "save canvas" button's behaviour, so that it'll use my function, and leave the NodeConnection and PortConnection as is, inheriting from NodeInput and NodeOuput.
     
    Last edited: May 4, 2016
  4. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    In order to make it save correctly, you have to inform the cache system of the editor window about the added knob. This happens by explicitly calling the callback for the created knob so it can be added to the save file:
    Code (csharp):
    1. NodeEditorCallbacks.IssueOnAddNodeKnob (newKnob);
    This has to be called manually as you don't want to have lots of these callbacks when the node has been created for the first time... I know, this can be improved.
    In the UnityFunc tree you can actually find a working example, the ActionNode (knobs are correctly created, but it is very complex and might not serve very well as a reference). I tried to create an example but there seems to be an issue where these knobs can not be used (no connection can be drawn from them), only after reloading the canvas. I have to take a look into this problem. This does not happen in the UnityFunc tree though.
    To delete them respectively, they now have a function called Delete to remove them correctly.

    Yeah extending the knobs may not be a good idea, though when casting them back to the correct type that should work. But not optimal.
    Try to store representatives along them (a list of answers stored seperatively, referencing the node knobs).
    Again, I have to resolve the adding of node knobs before this part works:(


    You can try that, the editor window is meant to be adjusted to each extension's needs.
    Though I'd first try other options before messing with scriptableObjects by extending the knobs... See above;)
     
  5. Aishiteru

    Aishiteru

    Joined:
    May 3, 2014
    Posts:
    31
    ah okay, just trying out something
     
  6. andxet

    andxet

    Joined:
    Jul 8, 2013
    Posts:
    4
    Hi!
    So my work is going on well, I've built the UI for the nodes: I have created a custom editor for my node class, and from the inspector I add and remove ports. Now I'm trying to select a knob to show a custom inspector for it. I will do it next week, but I'm looking for how to do it. I have to find the part about "onclick" in NodeEditorWindow and use the Unity's editor command to acquire focus, I think. I saw funciton that permits to obtain the knob if you click in it.

    I'm a little worried about the edges: it is possible to obtain the knob when clicking on the curve who link tho nodes? There is a part of unity manual where I can find information about?

    Thank you
     
  7. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    So, you found the function where the input is handled? It is in the NodeEditorInputControls.cs file, function HandleConnectionDrawing (line 159 of you have the latest version). There, the connection 'drawing' (here in the sense of creating) is handled. If you want to be able to select knobs, you can add an extra checks to only create a connection when you left-clicked, but select it when you right-clicked (or something similar). That should do it :)

    But I think what you are trying to do can be made easier. Why storing the answer data in the nodeOutputs themselves, not in the Node? Then you have no complicated work to do like this, you just need an acompanying list for each answer knob that holds the data.

    Or, if you don't want to change much, instead of making the knobs selectable, you could display their data IN the nodes instead, so if your answer data contains a string, you can make it display in the node, right?
     
  8. Aramilion

    Aramilion

    Joined:
    Apr 15, 2016
    Posts:
    23
    So there're still problems with switching from Play mode back to Edit Mode.
    When i do so, i got 2 errors:
    1. UnityException: Knob texture could not be loaded!
    NodeEditorFramework.NodeKnob.ReloadKnobTexture () (at Assets/Plugins/Node_Editor/Framework/NodeKnob.cs:66)
    2. ArgumentException: Getting control 1's position in a group with only 1 controls when doing Repaint
    Aborting

    I don't know if i'm doing something wrong or what?
    I'm using Unity 5.1.2f1 if this information can help
     
  9. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    I don't get them anymore.... proof:

    ;)

    I currently do not have 5.1.2 installed, 5.3.4; Perhaps you can try a similar version and see if that fixed it?
     
  10. Artiste

    Artiste

    Joined:
    Dec 12, 2014
    Posts:
    12
    I don't get it. The node editor behaves the same way, whether we are in playmode or not. We can create an new canvas in playmode, add nodes, save it, and it will remain in this state when we exit playmode. Am I missing something?

    Right now we're skipping the runtime live traversal of the behaviour trees (even though it would look pretty cool and help debugging unexpected behaviours), to focus on adding Undo functionalities, as it seems to be a requirement if we want to share our Behaviour Tree editor on the Unity Store.
     
    Last edited: May 10, 2016
  11. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    With runtime I mean true runtime - builds on any platform.
    You might think there are other things to focus on, but a guy on GitHub needed this for Android Arduino programming, which I'm interested in, too. So it is a feature that is uncommon but needed.

    Undo functionality is definitely something we have to take care of, but with the current Undo system it is a real pain:(
    I aproached a different, reflection based action-based solution integrated into the default Undo system (basically recognising the undo/redo of dummy entries and handling associated undo/redo actions). I had in mind to make use of this, depending whether I'll be able to finish it (logic behind it is fortunately working) and whether we want to take the cost of yet another reflection based method (next to zooming, even though both are VERY fast).
    Thanks for reminding me on that, I'll take a closer look at that action based undo integration of mine, haven't worked on it for months:)
     
    UnLogick likes this.
  12. Artiste

    Artiste

    Joined:
    Dec 12, 2014
    Posts:
    12
    Oh, right, when I talked about runtime I meant the traversal of our trees next to the game window while we play test inside Unity. Our version of the editor isn't supposed to be built separately, it's only here to generate the Behaviour Trees that will be used in the actual game you'll build. Can be in the same project, or added to an other one even. (just add the .cs files generated to your resources folder).
     
  13. Aramilion

    Aramilion

    Joined:
    Apr 15, 2016
    Posts:
    23
    Am i missing something? It is still not working unfortunettly. :(
    I download lastest build from GIT (it's dated on 6th April), and it doesn't work.
    Than i want to make thoose changes you linked here https://github.com/Baste-RainGames/Node_Editor/commit/cc44390260ae2618b2cb67558422d61ab77d67b5
    But thoose files are completly different.

    This fix you wrote about is also dated on 12 days old. So it is newer version (i suppose) from what i see on https://github.com/Baste-RainGames/Node_Editor

    I don't rly get it. I know i'm doing something wrong. but don't know what. :(

    Althou beside this everything works damn good! I'm making an Editor to help you do touch applications. Like on Museums you have this big touch screen with content in it (so you can scroll, click and learn :D). So I want to use Your framework to automatise lots of work needed to be done. And it will be more clear to look at connections in application.

    [EDIT] if it's the branch... i can try one more thing (i understand why they are and how they works, but not how to use them yet.) and if it is, i'm gonna take a day off :D

    [EDIT2] got it working. but. first time i start there is an error and missing references. but it is not a problem. it works after it fine. But i cannot start the same project 2nd time! I got an Unity Error, and it asks me to send a BugReport,
    http://pastebin.com/B0PWCMzQ
    this is log with an error i found.
     
    Last edited: May 11, 2016
  14. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Yes, I committed it into the branch develop, because I'm used to it:) I recommend to use download the develop branch, even though it might not be fully stable.
    Regarding the error, it might pop up because I forgot a meta or anything similar, as I said it is the develop branch...
    I experienced a similar crash too a few months ago but I fixed it, maybe it's just some constellation of this built but I definitely have to check this out... :/

    Anyway, UndoPro makes good progress, revisiting a very old project is sometimes very eye-opening;)
     
  15. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Can you send me your editor.log file after a crash (or just the stack traces at the bottom should be fine, too)? That would very much help me tracking this crash down:)
     
  16. Aramilion

    Aramilion

    Joined:
    Apr 15, 2016
    Posts:
    23
    Thanks for quick responses.
    I tried your develop branch, but it still makes crash when i want to open project second time.

    Here is Editor Log you've asked for:

    EDIT: Trying to fix it with my coworker for 3 hours. we don't rly know why is it happening. Hope you will help us somehow! :D
     

    Attached Files:

    Last edited: May 12, 2016
  17. Aramilion

    Aramilion

    Joined:
    Apr 15, 2016
    Posts:
    23
    Fun fact. What fixed the problem with canvas reseting after returning from Play Mode to Edit Mode, is simply closing the NodeEditor window... Canvas is remembered, so no references are lost. and no error. Just open it again and it works! :cool:

    I know this do not FIX the problem, but now i'm a lot calmer since i know i am able to make it work some way by myself! :)

    EDIT: Didn't even thought about it earlier! which can be cinsidered sad :/
     
  18. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Well then... The editor log unfortunately does not have a stack trace, it'd get way more complex than this.
    Can you send me (PM?) the canvas file that will cause an error on start up? Or if it's not too much of a trouble, a video?
    But fortunately there is a workaround, though it is annoying I suppose...
     
  19. Aramilion

    Aramilion

    Joined:
    Apr 15, 2016
    Posts:
    23
    Have to go now. will send tommorow in the morning. But thoose problems occour with the bare project i download from your develop branch. with any canvas.
     
  20. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    So I just checked both versions and checked them for any errors in common situations. These are now 'officially' known:
    In MASTER:
    - Errors and canvas unload on playmode leave; Fixed once merged with develop
    In DEVELOP:
    - None
    In BOTH:
    - Errors and canvas unload on scene load; Not fixable right now because no callback is avaiable, but I will work on it:)
    - Meaningless error when first imported and lastSession.asset is missing; planned to fix this

    I don't know of any other problems, atleast none that I can reproduce.
    If you find other problems, please write it here, with an explanation what you did before and whether it can be reproduced (atleast on your machine), post the errors, at best with the canvas and the error.log if Unity crashed. That'd be great, thanks!
    So, @Aramilion if you can send me the canvas when you have time that'd be great:)

    I desperatively need to merge develop into master in one iteration, because master is behind develop with so many features. In the same load I want to merge the groups feature into develop as it is fully working now; Any other features will likely not make it into the mostly stable develop in this iteration:/
     
  21. Aramilion

    Aramilion

    Joined:
    Apr 15, 2016
    Posts:
    23
    To reporoduce Unity Crash.
    1. Download Node_Editor-develop from Git Hub
    2. Create new folder. name it for the sake of certain steps: "Node_Editor_5.3.4"
    3. Create folder named Assets in this filder
    4. repack the *.zip file you have downloaded in this Assets folder
    5. You CAN but don't have to put Node-Editor folder in Plugins folder
    6. Open Unity 5.3.4
    7. Select "Open Project"
    8. Select the folder we created earlier ("Node_Editor_5.3.4")
    9. Wait till Unity will open
    10. Open Node_Editor window by going Window -> Node Editor
    11. Load exising canvas using "Load Canvas" from SidePanel
    12. Use play button to enter Play Mode.
    #sometimes here you get an error about missing references. You need to proceed to folders: Assets -> Node_Editor-develop -> Editor -> Node_Editor, and delete LastSession.asset file. This will fix the errors. Than proceed to "point 10" and do thoose things again.
    13. Everything worked now, so click Play button again to stop Play mode.
    14. Everything is working. :) Seneral is the best!
    15. Close Unity!
    16. Do not save the scene!
    17. Open Unity 5.3.4 (again. the same version)
    18. Open project we have just created.
    19. Wait a bit
    20. Get Unity Bug Report window with all this staff I've sent to you
    21. Seneral is still the best, but i got sad :(

    So basicly i do not create anything new. everything is in your files from the beginning. But somehow i manage to crash it. Every time. on 3 different computers. Even on Earlier Unity versions.

    Fun fact: Unity 5.1.2 does not show the Bug Report window. it just exit the process.

    PS. the Log is posted higher
     
  22. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Ok, could reproduce it now. Strangely, the crash could even be reproduced by simply exiting unity while the window is open...
    So as the editor.log wasn't very helpful without a stack trace, I investigated how I could fix the broken project by deleting files. Deleted everything but the assets folder did not work for some reason, so I deleted every created meta file, and that did it. In the end, it was the Editor Window meta file which prevented the window from starting. That took me embarassingly long to get:/
    So I checked the editor window init code and disabled GUI code, and found it was the NodeEditor init call in OnEnable (the one some frames later in OnGUI was fine).
    By disabling the init function step by step I found it to be GUIScaleUtility, even though I did not change it in onths and I never experienced a similar crash, but I have the window open when restarting all the time...
    Anyway, in the GUIScaleUtility it was the final try-catch block that should check if the system works, and else compability mode should be enabled - the TRY-CATCH block! :eek: Actually, the line in the TRY block - wtf? :confused:
    Just - look at it:
    Code (csharp):
    1.  
    2. try
    3. {
    4.     topmostRectDelegate.Invoke (); // This causes the crash :O
    5. }
    6. catch (Exception e)
    7. {
    8.     Debug.LogWarning ("GUIScaleUtility cannot run on this system! Compability mode enabled. For you that means you're not able to use the Node Editor inside more than one group:(");
    9.     Debug.Log (e.Message);
    10.     compabilityMode = true;
    11. }
    12.  
    For what reason did I put the try-catch block there? o_O Btw, putting a throw new Exception there is totally fine:confused:
    Anyway, I'll investigate this for the future, but for right now, you can just comment this block, if it causes the crash it is unusable...

    I have the suspect that on OnEnable the GUI system isn't yet initialized and so the delegate asking the GUI system to return the groups will crash unity - sounds legit :/
     
    Last edited: May 13, 2016
  23. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Good news everyone on the Undo support!
    Wednesday, Thursday and Friday I polished UndoPro as is, made it reliable (more reliable, to be precise). But the recorded actions still got lost on script reload or playmode change...

    Action Serialization
    So I approached the next, BIG hurdle: Serialization of the Undo actions. That is one really important but also very challenging task. I only had hopes to make known (non-anonymous) actions work, because anonymous actions are... strange. Compiler generated and not serializable namely. But anonymous actiosn are very important for undo actions, maybe even essential, as they allow you to include the context of the function into the action (local variables, f.E.).:confused:
    So I did some research (mainly with this question), and thanks to Bunny and Vexe (this answer) soon finished the serialization of normal actions. Cool! :cool:

    But Bunny had even helped to make the concept of serializing anonymous delegates/actions, and full of hope, I started developing it. I faced some serious problems with actions using local variables as they are instantiated in a compiler-generated, own class, but with a minimal own serialization system I finally managed to serialize both normal and anonymous action, with nearly no restrictions to target or method! :eek:
    Due to the nature of UndoPro I only accounted for actions with no parameters and single-cast only! With a bit modification both features can be added though:)

    Supported are both UnityEngine.Object and System.Object types, even basic non-serializable types (atleast it's members that are serializable). Methods aswell as classes the methods are within may have generic parameters! Also, normal and anonymous methods are equally serialized, same conditions apply here, though: For anonymous actions referencing local variables, variables of serializable type, system- or unityengine, will work just fine, but non-serializable objects will get the default value or null assigned if previously null. So basically nearly any actions will serialize, with exception of some very rare, complex scenarios. I think that suffices as a base of UndoPro!

    Back to UndoPro
    I posted the source in the above linked question, and now I'm stress-testing the undo tracking system by sending it through playmode and selection change combinations (latter ones are nasty, they often create an anomaly of duplicated or removed entries, and they are not considered important enough to clear redo, f.E.; They are just a class of their own and hard to handle:( ). So I still need some time making the tracking absolutely solid.:cool:

    I expect it to work atleast by the end of the week (no promises though), and then I'll have fixed yet another one of many developer nightmares: The undo system:D (Next to solid GUI Scaling and anonymous action serialization).
    After that we're able to painlessly implement undo support for the Node Editor Framework!
     
    Marble likes this.
  24. dustinandrew

    dustinandrew

    Joined:
    Apr 30, 2010
    Posts:
    95
    Great work @Seneral

    I wrote a simple example Quest Node for anyone that is looking to get started creating custom nodes:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System;
    4.  
    5. using NodeEditorFramework;
    6. using NodeEditorFramework.Utilities;
    7.  
    8. [Serializable]
    9. public class Quest {
    10.     public int ID = 0;
    11.     public string Title = "";
    12.     public string Body = "";
    13. }
    14.  
    15. public class QuestType : IConnectionTypeDeclaration {
    16.     public string Identifier { get { return "questNode"; } }
    17.     public Type Type { get { return typeof(Quest); } }
    18.     public Color Color { get { return Color.cyan; } }
    19.     public string InKnobTex { get { return "Textures/In_Knob.png"; } }
    20.     public string OutKnobTex { get { return "Textures/Out_Knob.png"; } }
    21. }
    22.  
    23. [Node(false, "Standard/Quest Node")]
    24. public class QuestNode : Node {
    25.  
    26.     public const string ID = "questNode";
    27.     public override string GetID { get { return ID; } }
    28.  
    29.     public Quest QuestObj;
    30.  
    31.     public override Node Create(Vector2 pos) {
    32.         QuestNode node = CreateInstance<QuestNode>();
    33.  
    34.         QuestObj = new Quest();
    35.         QuestObj.Title = "Quest Node";
    36.      
    37.         node.rect = new Rect(pos.x, pos.y, 200, 200);
    38.         node.CreateInput("Quest", "QuestType");
    39.         node.CreateOutput("Quest", "QuestType");
    40.      
    41.         return node;
    42.     }
    43.  
    44.      protected internal override void NodeGUI() {
    45.         if (QuestObj == null) {
    46.             QuestObj = new Quest();
    47.         }
    48.         GUILayout.Label("ID:");
    49.         QuestObj.ID = EditorGUILayout.IntField(QuestObj.ID);
    50.  
    51.         GUILayout.Label("Title:");
    52.         QuestObj.Title = GUILayout.TextField(QuestObj.Title);
    53.  
    54.         name = QuestObj.Title;
    55.  
    56.         GUILayout.Label("Body:");
    57.         QuestObj.Body = GUILayout.TextArea(QuestObj.Body, GUILayout.Height(65));
    58.  
    59.         GUILayout.BeginHorizontal();
    60.         GUILayout.BeginVertical();
    61.  
    62.         foreach (NodeInput input in Inputs)
    63.             input.DisplayLayout();
    64.  
    65.         GUILayout.EndVertical();
    66.         GUILayout.BeginVertical();
    67.  
    68.         foreach (NodeOutput output in Outputs)
    69.             output.DisplayLayout();
    70.  
    71.         GUILayout.EndVertical();
    72.         GUILayout.EndHorizontal();
    73.     }
    74.  
    75.     public override bool Calculate() {
    76.         if (!allInputsReady()) return false;
    77.         return true;
    78.     }
    79. }
    80.  
     
    Last edited: Jun 29, 2016
  25. Aramilion

    Aramilion

    Joined:
    Apr 15, 2016
    Posts:
    23
    Hey, it's me again. I have a trival question about doing something.
    My nodes contain a public reference to GameObjects they are refering to. (1 node == 1 gameObject). so simple Node canvas is a visual representation of my Hierarchy.

    After reloading Unity. Simple by exiting and opening a project once again, I loose them. I loose all thoose references, and since my script i built this way it is, when there is no reference to a gameobject, just create one from prefab and go on. (this behaviour is needed)

    So basicly what i have to do is before creating a gameobject, i have to check if the item this node is refering to already exist, if it is, just update this reference. I could accomplich it by checking an unique name of my GameObjects, and match them with name of nodes... but this sucks and i don't wanna do that. Coparing strings ;-;

    So next method i've look at was using
    Code (CSharp):
    1. GameObject.GetInstanceID();
    2. EditorUtility.InstanceIDToObject(int id);
    But it also doesn't work, couse howewer the id's are unique, they're lost upon loading scenes... which i do after reloading the application.

    I don't have to save nor load canvasses. I just want to open project, and be able to work on it.

    Summary:
    After Reopenning Unity, nodes saved in canvas loose references to SCENE gameobjects.
    I know it's an issue i have and the behaviour is intended. but i just ask if you could have a simple solution to fix it?
     
  26. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    First off, you need to save the canvas in order to use it in the next session obviously. This is currentlyonly done by creating an asset, and it's not allowed to reference scene objects from an asset.
    I've already thought about this and it is possible to store the canvas with the scene instead, so you'll be able to reference scene objects without problems:)
    I'll try to set this up real quick:)
    Edit: Cut the 'real quick' out please;)
     
    Last edited: May 23, 2016
  27. Gekigengar

    Gekigengar

    Joined:
    Jan 20, 2013
    Posts:
    460
    Is it possible to create a node without knobs like these ones while using the same input/output system.?
    I need my nodes to be without knobs.

    So users only need to right click, then click on "Connect Nodes" to create a curve that connects one another.
     
  28. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Yep, it's totally possible. But if you want to use the existing connection system, it makes sense to not treat them as rectangles on the node with textures, as they are right now. I recommend to isolate the connection functionality out of NodeInput/NodeOutput and make these seperate classes, and each node has such a connection object by default.

    Then you can use the new dynamic input system (implemented only in the develop branch for now) to add a node context menu to add this functionality:)
    You can take a look at NodeEditorInputControls for examples, but basically the function needs the ContextEntryAttribute of type node;)
    The input could look like this:
    Code (csharp):
    1.  
    2. [ContextEntryAttribute (ContextType.Node, "Add Connection")]
    3. private static void StartConnectionDrawing (NodeEditorInputInfo inputInfo)
    4. {
    5.     inputInfo.SetAsCurrentEnvironment ();
    6.     NodeEditorState state = inputInfo.editorState;
    7.     if (state.focusedNode != null)
    8.     {
    9.         // TODO: Activate connection drawing state
    10.     }
    11. }
    12.  
    13. [EventHandlerAttribute (EventType.MouseDown)]
    14. [EventHandlerAttribute (EventType.MouseUp)]
    15. private static void ApplyConnectionDrawing (NodeEditorInputInfo inputInfo)
    16. {
    17.     inputInfo.SetAsCurrentEnvironment ();
    18.     NodeEditorState state = inputInfo.editorState;
    19.     if (state.focusedNode != null && ConnectionDrawingState == true)
    20.     {
    21.         // TODO: Apply the drawn connection to the focused node
    22.     }
    23. }
    24.  
     
    Last edited: May 23, 2016
    Gekigengar likes this.
  29. Aramilion

    Aramilion

    Joined:
    Apr 15, 2016
    Posts:
    23
    Why sometimes
    Code (CSharp):
    1. NodeEditor.curNodeCanvas == null
    ?

    Of course i'm sure there are Nodes. But jus wanna know if they are moved somewhere for a little time or what?
    I need to have a constant access to the node list. Sometimes it works, sometimes this is set to null.

    The similar thing is that sometimes NodeEditor.curNodeCanvas != null but it contains only null Node objects.
     
    Last edited: May 30, 2016
  30. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    From where do you access this value? It is only meant to be accessed by any elements involved in the actual framework, like nodes, etc.
    This variable is only set during the draw and calculation phase, then it will be nulled again.
    If you want to get the currently loaded canvas instead, you should use NodeEditorWindow.mainNodeCanvas:)
    These are seperated because the actual window does not belong to the framework, and as multiple canvases loaded at once are supported, NodeEditor.curNodeCanv as can not be constantly set to one value;)
     
  31. WamboGer

    WamboGer

    Joined:
    Dec 13, 2015
    Posts:
    2
    Hi, just wanted to thank you for this NodeEditor Framework. It took a while to get the hang of it and i honestly feel like the code is at some points a bit messy. But hey it works, u share it with us for free and actively support and enhance it. And once you're in you can edit it to your needs. I'm really looking forward to a more modularized version.

    Here is a screenshot of my work in progress Node-Based Noise Shader Editor.
    NoisyPreview.jpg
     
  32. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    That is seriously looking really good! :)
    I agree that some parts are a bit messy or atleast not very well designed, but in comparision to the master branch the develop branch evolved alot in this regard and alot of systems were cleaned up. Maybe it's worth checking the develop branch out until I find time to merge it into master;)
     
    WamboGer likes this.
  33. josessito

    josessito

    Joined:
    Feb 14, 2014
    Posts:
    56
    Hi! @Seneral This looks great! I whant to do a dialog system and I was thinking to use this, however I'm not sure how to create my own nodes to accept a scriptable object or a gameobject as a variable, instead of a float, a string or a color... I am also a little bit lost on how can I get in or out the information from the nodes... Maybe this is a little over my head.
    Thanks!
     
  34. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    For custom nodes and custo connection types, see the documentation about this (it's old, but works...).
    Basically you can reference anything not in the scene (I'm working on that) by adjusting the GUI. For a scriptable object, you might want to take a look at EditorGUILayout.ObjectField.
    You can access all nodes from NodeEditorWindow.mainNodeCanvas from other editor scripts.
    Hope that helps you get started, would write up more but am short on time:)
     
  35. TheValar

    TheValar

    Joined:
    Nov 12, 2012
    Posts:
    759
    I'm also interested in making a dialogue editor. In the provided examples the node connections and node types seem to be concerned with passing values from one node to another, so how would I go about creating custom node connections that are literally just links between nodes?
     
  36. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    I made an example in this post, along with an example to get adjacent connections from within the node. You can find the same node as an example node in the devlop branch, here.
    Basically, you can set the connection type to typeof(void) to emphasize that it's only visual (doesn't need to though, technically), and then just ignore the connection when checking for the state in the calculation funciton (if you use it).
    Tell me if that's what you expected:)
    I do plan on extending the connections to be more versatile and not so tailored to calculation though...
     
  37. TheValar

    TheValar

    Joined:
    Nov 12, 2012
    Posts:
    759
    Yup that's exactly the info I was looking for thanks a lot!
     
  38. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Hey guys, check out the new update in the develop branch:

    Added ability to save to scene, completely reworked save system

    Changelog:
    Maybe I should also note that scene saving currently does not support any kind of caching like the asset saving does... I also did not implement deleting saves and checks if you really want to overwrite a file or something similar yet - so be careful!
     
    Last edited: Jun 7, 2016
  39. Aramilion

    Aramilion

    Joined:
    Apr 15, 2016
    Posts:
    23
    Oh You made it! <3

    Have a few questions about it and a feedback.
    1. So You cannot now save the nodeCanvas in asset after you saved it in Scene?
    2. How do I install it? couse it keeps giving me this error while going to Play mode:
    And yes, it DOES point to LastSession.asset (debugged it). I've changed a little bit a folder structure, but even when i put new Framework directly to Assets it doesn't work.

    3. The button "Load from Scene" were responding like once every 5 clicks. Took me time to figoure how to make it work every click. Bacisly if you click on the left of button, everything is ok, the PopUp menu is showing, but when you click to far to right, the popup menu will not show. (i think couse a coursor is to far from it, and it thinks it would be a good idea to close itself :) stupid menu... :))

    Anyway great work! I really like how active people here are! I'm going to change to this version of Framework if only i figure out what to do with this error.
     
  40. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Good points, thanks! I'll resolve them asap:)
    1. one I thought it would be a good idea because if you referenced scene data it might be corrupt after saving to scene, but after thinking about it it might aswell be useless if you are aware of that... I'll fix this!
    2. and 3. are obviously bugs and they'll be fixed aswell.
    Thanks for the reports!
     
  41. Game-Dragon

    Game-Dragon

    Joined:
    Nov 16, 2012
    Posts:
    6
    So would I go about creating input and output knobs dynamically? I'm having trouble getting them to display.
     
    Last edited: Jun 11, 2016
  42. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    @Game Dragon Ah, see you edited to knobs, know I understood:)
    I've built something similar in the past for the action node, but that would be too complex because there's alot of other stuff going on. So I made a little example...
    This node is just like the calculation node but with a variable number of inputs and calculation type for each input:)
    Code (csharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections.Generic;
    4. using NodeEditorFramework;
    5. using NodeEditorFramework.Utilities;
    6.  
    7. namespace NodeEditorFramework.Standard
    8. {
    9.     [Node (false, "Example/Dynamic Calculation Node")]
    10.     public class DynamicNode : Node
    11.     {
    12.         public enum CalcType { Add, Substract, Multiply, Divide }
    13.         [Serializable]
    14.         public struct InputData
    15.         {
    16.             public float value;
    17.             public CalcType type;
    18.         }
    19.  
    20.         public const string ID = "dynamicNode";
    21.         public override string GetID { get { return ID; } }
    22.  
    23.         public List<InputData> inputData = new List<InputData> ();
    24.  
    25.         public override Node Create (Vector2 pos)
    26.         {
    27.             DynamicNode node = CreateInstance<DynamicNode> ();
    28.  
    29.             node.rect = new Rect (pos.x, pos.y, 300, 200);
    30.             node.name = "Dynamic Calculation Node";
    31.  
    32.             node.CreateInput ("Base", "Float");
    33.             node.inputData.Add (new InputData ());
    34.             node.CreateOutput ("Output", "Float");
    35.  
    36.             return node;
    37.         }
    38.  
    39.         protected internal override void NodeGUI ()
    40.         {
    41.             if (GUILayout.Button ("Add Input"))
    42.             {
    43.                 NodeInput newInput = CreateInput ("Input " + (Inputs.Count+1), "Float");
    44.                 NodeEditorCallbacks.IssueOnAddNodeKnob (newInput);
    45.                 inputData.Add (new InputData ());
    46.             }
    47.  
    48.             for (int cnt = 0; cnt < Inputs.Count; cnt++)
    49.             {
    50.                 InputData data = inputData[cnt];
    51.                 NodeInput input = Inputs [cnt];
    52.                 GUILayout.BeginHorizontal (GUILayout.MaxWidth (rect.width));
    53.                 if (input.connection != null)
    54.                     GUILayout.Label (input.name + ": " + input.GetValue<float> ());
    55.             #if UNITY_EDITOR
    56.                 else
    57.                     data.value = UnityEditor.EditorGUILayout.FloatField (input.name, data.value);
    58.                 if (cnt > 0)
    59.                 {
    60.                     data.type = (CalcType)UnityEditor.EditorGUILayout.EnumPopup (data.type);
    61.                     if (GUILayout.Button ("-", GUILayout.Width (20)))
    62.                     {
    63.                         input.Delete ();
    64.                         inputData.RemoveAt (cnt);
    65.                         cnt--;
    66.                         continue;
    67.                     }
    68.                 }
    69.             #endif
    70.                 GUILayout.EndHorizontal ();
    71.                 InputKnob (cnt);
    72.                 inputData[cnt] = data;
    73.             }
    74.  
    75.             Outputs [0].DisplayLayout ();
    76.  
    77.             if (GUI.changed)
    78.                 NodeEditor.RecalculateFrom (this);
    79.         }
    80.  
    81.         public override bool Calculate ()
    82.         {
    83.             float result = 0;
    84.             for (int cnt = 0; cnt < Inputs.Count; cnt++)
    85.             {
    86.                 InputData data = inputData[cnt];
    87.                 NodeInput input = Inputs [cnt];
    88.                 if (input.connection != null)
    89.                     data.value = input.connection.GetValue<float> ();
    90.                 inputData[cnt] = data;
    91.  
    92.                 if (cnt == 0)
    93.                 {
    94.                     result = data.value;
    95.                     continue;
    96.                 }
    97.  
    98.                 switch (data.type)
    99.                 {
    100.                 case CalcType.Add:
    101.                     result += data.value;
    102.                     break;
    103.                 case CalcType.Substract:
    104.                     result -= data.value;
    105.                     break;
    106.                 case CalcType.Multiply:
    107.                     result *= data.value;
    108.                     break;
    109.                 case CalcType.Divide:
    110.                     result /= data.value;
    111.                     break;
    112.                 }
    113.             }
    114.             Outputs[0].SetValue<float> (result);
    115.  
    116.             return true;
    117.         }
    118.     }
    119. }
    Screenshot1.jpg

    It's not too polished, beware! ;) Also alot of the stuff going on here is still because of the design (the list that holds information about these inputs for example). The core of adding Inputs is:
    Code (csharp):
    1. NodeInput newInput = CreateInput ("Input " + (Inputs.Count+1), "Float");
    2. NodeEditorCallbacks.IssueOnAddNodeKnob (newInput); // Event to notify the cache
    and for removing:
    Code (csharp):
    1. input.Delete ();
    The same applies to Outputs:)
     
  43. LucaHofmann

    LucaHofmann

    Joined:
    Feb 24, 2015
    Posts:
    12
  44. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Yeah there are definitely possible issues for different use cases in my project (I'll simply call it like that to distinguish), as it's not as generalized yet. I hope yours will help people that require other needs not adressed in my project yet:)
    But I think one generalized node editor that is flexible enough for a multitude of use cases is the 'ultimate goal' to achieve;)

    Also, I do not have too much time recently as you might have noticed, I'm in exam phase right now:/
     
  45. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Just committed a new update to develop, which can be found here!
    It adresses all issues @Aramilion mentioned, and more:
    Sorry that it did rather long to fix these:/

    EDIT: Here's the scene saving in a GIF:
     
    Last edited: Jun 15, 2016
  46. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    In preparation of the upcoming, long overdue merge of develop into master, I merged the few master changes into develop first with this commit. After a short period of testing time of about 1-4days I plan to finally update master.
    This is a very important step because I didn't care about it for a long time, so master is actually way behind develop and develop is way more stable;)

    Note that the change log is rather short despite the many commits to master because many fixes to master were already incorporated into develop over time.
    Also I did not merge the changes of for loops to foreach loops, if you want you can do that but it was a bit too much for my taste for a manual merge;)
     
  47. Aramilion

    Aramilion

    Joined:
    Apr 15, 2016
    Posts:
    23
    I think there is something silly in develop now.
    I create canvas with my nodes, go to play mode, and the canvas is disappearing.
    I cannot load it, and adding nodes there is highly difficult. (similar problem to last load from scene button), the context menu doesn't always shows up. I managed to create some canvas in play mode thou and saved it.
    When i stop testing, i can normally load my previous canvas. but the one i saved in play mode is not visible. What's more, When i enter play mode again, my canvas disappears and the one i saved in play mode appears.
    I kind of liked the ability to actually see the canvas during play-testing.

    I can't wait for the final merge! :)
     
  48. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Huh, then it was probably an error when merging, didn't had any issues in my projecto_O That's what the testing period is for:)
    Besides, compared to the last commit, I didn't changed anything that could have affected this:confused:
    I'll take a look later!
     
  49. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,200
    Ok, so I'm currently checking the mentioned errors.
    The saving issues are caused by interferences between scene saving and the asset caching system. As you know scene saving does not support caching, and so when starting playmode the scene canvas is lost. So far, expected. Then, the caching system will go in and will actually load the last loaded asset-saved canvas still stored as the lastSession. I'll fix this, most probably by adding support for scene-save caching:)
    The issue that you cannot open the context menu in playmode is caused by a strange mix of positioning issues. In short, the context menu is opened 22pixels below the mouse cursor (because of the window header) which will cause the context menu to close immediately if you wouldn't move the mouse below faste enough.
    Both issues persisted since the save system was introduced nine days ago...
    I'll commit a fix hopefully later this day:)
     
  50. TheCaptainJuneBug

    TheCaptainJuneBug

    Joined:
    Sep 29, 2013
    Posts:
    9
    How would you go about making a tree using this node editor. Like have a root and a bunch of child nodes that reference their parent node? Ive dont it buts its a bit messy, was wondering if you have a better way.
     
unityunity