Search Unity

xNode - A general purpose node editor

Discussion in 'Assets and Asset Store' started by Siccity, Oct 30, 2017.

  1. pvanallen

    pvanallen

    Joined:
    May 19, 2017
    Posts:
    5
    Hah! Right, of course. I just meant better than manually creating them.
    NodeEditorWindow.current.Repaint();
    worked!
     
  2. D3Duck

    D3Duck

    Joined:
    Dec 25, 2014
    Posts:
    45
    This is probably a bit more of a general Unity question, but since I'm using your framework (its great btw) I thought I'd check here in case there is something I'm not aware of.

    I made a simple graph with only one node so far valueNode : Node. It only has a public float input and another output. GetValue just returns the input value as per the example node. What I want to do is make a node that allows you to either input a float value or display a float that is sent in through the input. Where things go wrong is in making the custom GUI. This is the main part of the code:

    Code (CSharp):
    1. public override void OnBodyGUI()
    2. {
    3.     if(target.GetInputPort("input").IsConnected)
    4.     {
    5.         EditorGUILayout.BeginHorizontal();
    6.         NodeEditorGuiLayout.PortField(target.GetInputPort("input"));
    7.         NodeEditorGuiLayout.PortField(target.GetInputPort("output"));
    8.         EditorGUILayout.EndHorizontal();
    9.     }
    10. }
    When I connect another port to it the GUI goes all wonky for some reason and I'm not sure why. Somehow the output port seems to move to the right and goes invisible due to not having enough space and the noodle just floats in the air to the right side of the node port, but messing with the input and output attributes and GUILayoutOptions did not resolve this for me.

    Any ideas on what I'm messing up or where to look would be appreciated.

    Also, thanks a lot for the framework. This is the first one out of about four that I've actually been able to understand for the most part.
     
  3. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    I'm not sure exactly what you are trying to do. But it sounds to me like you're trying to make something similar to DisplayValue in the MathGraph example?
    Doing this, to me, sounds like you don't need to rework the default GUI, as it already does allow you to input a value unless connected. Instead, just add the displayed value if an input is connected. You can use base.OnBodyGUI(); to draw default GUI.
    Code (CSharp):
    1. public override void OnBodyGUI()
    2. {
    3.     base.OnBodyGUI();
    4.     if(target.GetInputPort("input").IsConnected)
    5.     {
    6.         EditorGUILayout.LabelField(target.GetInputValue("input"));
    7.     }
    8. }
    This should do what you described.

    As for the ports behaving oddly, maybe it's caused by both your input and output being found using GetInputPort? Try using GetOutputPort for the output instead, if that fixes it. Generally placing an input and an output on the same line is a bit tricky, but definitely possible and I've seen it done before. :)

    EDIT: Placing input and outputs on the same line is now easier using NodeEditorGUILayout.PortPair
     
    Last edited: Sep 20, 2018
  4. pvanallen

    pvanallen

    Joined:
    May 19, 2017
    Posts:
    5
    Sorry, one more question. Is there a way to reference NodeEditorWindow.current.Repaint(); from within the node context rather than its editor? Or more generally, how can I reference the corresponding editor from within a node?

    For my application, control is passing from one node to the next based on external conditions without interaction by the user, and I want the graph to update as things change. Basically a behavior tree that shows status as things progress.
     
  5. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Unity places editor code in a different assembly so you can't directly access NodeEditor stuff from runtime scripts. But one way you could call editor code from nodes is through delegates. You can add a static delegate in the node, then in the editor code, subscribe to it with a method that calls Repaint();
     
  6. Vortex-The1st

    Vortex-The1st

    Joined:
    Jun 14, 2018
    Posts:
    1
    First of all let me say thank you for creating this awesome plugin! However there are a three things that I would like to ask/suggest:
    1. The preferences do not save properly, atleast for me that is. Whenever I hit play, the type colors get reset. This also happens when I recompile/change my scripts. It seems like something gets lost during the serialization. I can not say, whether this is only happening to me or if this is a common problem, so that's why I would like to ask.
    2. Sometimes, depending on how the code is structured, the name of the namespace can become quite long. So using that as the default title for newly created nodes is a little bit inconvinient in some situations. I'd suggest using the actual name of the type instead of the full namespace to make it less cluttered. I think an option in the preferences would be a good solution since using the namespace could also be useful in other cases.
    3. Moreover I'd appreciate an option to set the default connectionType for the in- and ouputs.
    That's it for now. I appreciate any response concerning the issue with the preferences because the autogenerated default colors sometimes are really horrid :).
     
  7. JDelekto

    JDelekto

    Joined:
    Jan 7, 2017
    Posts:
    49
    I think I have a solution for the Cut/Copy/Paste context bug. I'm using Unity 2017.3.1f1, and when attempting to rename a node, it pops up the Cut/Copy/Paste context dialog and I have to dismiss it in order to edit the header label.

    However, if in NodeEditorAction.cs, right after the call to ShowNodeContextMenu(), I add the line "e.Use();", it appears to keep the event from triggering the context menu. It seems like when making the header label editable, the edit control is getting the right click event as well and popping up the menu. I notice this happens on other input fields in general.
     
  8. JDelekto

    JDelekto

    Joined:
    Jan 7, 2017
    Posts:
    49
    I would like to say thank you very much for this asset, it's an awesome tool and really like the way it is organized! I have some ideas of how I want to use this; however, there is something I have been struggling with and I'm sure it has to be something really, really simple.

    I created a simple "Math Node" which has two input nodes (two floats, value1 and value2) and one output called "Result" which is just a sum of the two nodes right now.

    I next created a very simple "Display Node", whose sole purpose is to take the output of the Math node and display its output. So, I've created the Display node with one Input "value" and I have a public string display field member in my node. GetValue() returns the value of the Input node and in the OnCreateConnection(), I get the value of the "to" node and set my string display value to its result.

    This works fine and displays the correct value when I connect up the node; however, when I change the input values on the math node, I expect to see the output value update, but I think that I need to somehow get some type of notification from the Math node that these have changed.

    Are there any delegates provided in the framework for the connections that I can use to capture when the nodes change so that I can update my outputs? If not, what is the recommended pattern for supporting this? I would like to change values as I edit them and see them update in real-time in the editor where applicable.
     
    JvanE likes this.
  9. JDelekto

    JDelekto

    Joined:
    Jan 7, 2017
    Posts:
    49
    Nevermind, had I just finished going through all the final posts on this last page, I would have seen your reply to @D3Duck on June 5th. The example for the custom editor to call GetInputValue() and display a label is exactly what I needed and it works just splendidly!
     
    Siccity likes this.
  10. Awesumo

    Awesumo

    Joined:
    Nov 6, 2011
    Posts:
    57
    Is this an editor-only plugin? Is it possible to expose graphs to end-users at runtime to create and edit graphs?
     
  11. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Base xNode is editor-only, yes. But all the API is exposed, so you can create your own runtime editors to fit with the graph systems. Check out 'RuntimeMathGraph' in the examples branch for a simple UGUI implementation.
     
  12. Razieln64

    Razieln64

    Joined:
    May 3, 2008
    Posts:
    129
    Hi, I'm looking at your solution and it seems really good! I was wondering if it's possible to not restrict the number of outputs of a node.

    I'd like to use your plugin to model graphs with nodes that could have an infinite number of directed connections that go to and from other nodes. I'm also curious to know if it's possible to specify directions for connections between nodes.
     
  13. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Yes yes and yes

    xNode does only what you tell it to do.
    • A single port can support multiple or a single connection.
    • You can add 'instance ports' to dynamically add/remove extra ports on your node
    • Nodes don't have a builtin 'direction'. They are 100% dependent on how you program them
     
  14. The_BenEvans

    The_BenEvans

    Joined:
    Jul 31, 2012
    Posts:
    139
    Just been trying this out, but it seems to be misbehaving, unless I'm doing something wrong.

    Each dialog node has 2 public strings (descriptionText and actionText), that I've set with the [TextArea] tag (tried it without, still no luck).

    Occasionally when I edit a node's actionText, another node's actionText is cut to about ~6 characters, but only in the xNode editor. The scriptable object still retains the full string.

    Something you've encountered before or any idea on a fix? Tried turning Autosave on/off in the preferences but that didn't help.

    upload_2018-7-12_13-12-4.png

    Using Unity 2018.2.0f2
     
  15. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    I've seen it happen and I've looked for a solution, but I honestly have no idea what causes it. Maybe it has something to do with marking ScriptableObject dirty, or updating it, but it doesn't seem to affect any other value type. Maybe it has to do with the way UnityEditor handles and caches editable text fields internally. I'm not sure.

    EDIT: This has been fixed
     
    Last edited: Sep 20, 2018
  16. Alessaint

    Alessaint

    Joined:
    Mar 21, 2011
    Posts:
    43
    Hi!

    First of all - what a nice, clean system! Thanks a lot! :)

    EDITED: I had a problem, but removed the description since in the end I figured it out by looking at your Dialogue system :)
     
    Last edited: Jul 18, 2018
  17. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,208
    I'm testing out using Xnode with UMA. UMA utilizes a bunch of Custom Property Drawers. These play havoc with xnode, generating the dreaded "Mismatched LayoutGroup.Repaint" error on things like EditorGuiLayout.BeginHorizontal.

    Is there a way to successfully use Custom Property Drawers that use EditorGuiLayout?
     
  18. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Why would UMA have any effect on xNode? I don't know of any way to use Layout features in PropertyDrawers, but googling the issue does yield some answers. I haven't tried any of the workarounds myself though. I've just used PropertyDrawers the way they were indended to.
     
  19. Jaimi

    Jaimi

    Joined:
    Jan 10, 2009
    Posts:
    6,208
    I see. We use them everywhere and they work just fine. Thank you for looking into it.
     
  20. Dunkelheit

    Dunkelheit

    Joined:
    Sep 3, 2013
    Posts:
    81
    Is this possible to run this node editor inside unity running process instead to use Unity.editor classes?
     
  21. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    No. The editor is strictly editor-only, and you will run into a lot of walls attempting to convert it. This is on purpose. Allowing runtime support would require a ton of extra code and maintenance.
     
  22. D3Duck

    D3Duck

    Joined:
    Dec 25, 2014
    Posts:
    45
    Look for Node Editor Framework. It is free and has runtime support, but is definitely more complex as well.
     
    Jaimi likes this.
  23. zakrzus1

    zakrzus1

    Joined:
    Jan 31, 2015
    Posts:
    9
    Hi!
    Is there any way to export/import whole node structure to/from JSON ?
     
  24. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Not built-in, but it could be implemented as an extension. xNode uses standard Unity serialization, and Unity doesn't come with a JSON parser that supports inheritance. But you could probably get the result you want using third party serializers.
     
  25. zakrzus1

    zakrzus1

    Joined:
    Jan 31, 2015
    Posts:
    9
    Thank you for your response, i'll try with JSON .NET
     
  26. simitro

    simitro

    Joined:
    Feb 13, 2015
    Posts:
    123
    Is there any way to input or output an abstract, serializable class? Thanks!
     
  27. Nexusmaster

    Nexusmaster

    Joined:
    Jun 13, 2015
    Posts:
    365
    Hi,
    is there an easy way to write the graph out to a file e.g. xml or binary? I tried Odin Serializer, but I think it didn't get the NodePorts right.
    (I like to read and write the graphs during runtime in a standalone, using the runtime graph)
     
  28. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Abstract classes work just as well as any other class. Just create a public field in your node and give it the input or output attribute
    [Input] public MyAbstractClass myInput;


    Not an easy way, no. But as I answered 3 posts above, it can be implemented as an extension. Perhaps the best approach is to just loop through the contents of the graph and write/read it using your own parser.
     
  29. simitro

    simitro

    Joined:
    Feb 13, 2015
    Posts:
    123
    Weird. For me,
    [Output] public Test output;

    creates a knob with
    [System.Serializable]
    public class Test {}

    but it doesn't with
    [System.Serializable]
    public abstract class Test {}


    Tried with latest release and latest commit. Any idea? Thanks!
     
  30. Nexusmaster

    Nexusmaster

    Joined:
    Jun 13, 2015
    Posts:
    365
    Thanks, but I tried all your suggestions, not really easy to get it working... so I decided to recreate the graph and save only the user inputs and paste them in the new graph; not the best solution but saves less and is easy to implement.
     
  31. zakrzus1

    zakrzus1

    Joined:
    Jan 31, 2015
    Posts:
    9
    Is this compatible with iOS and AOT compiler?
     
  32. tmcgillicuddy

    tmcgillicuddy

    Joined:
    Jul 8, 2014
    Posts:
    6
    I'm having an issue where nodes will disconnect or I need to clear instance ports for some reason. Is there a quick fix for this/ a known bug?
     
  33. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    When do they disconnect and why do you need to clear instance ports? Which version are you on? You need to tell me more.
     
  34. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Asset store update :D
    xNode has been updated to version: 1.5

    This includes:
    • Added NodeEditorGUILayout.AddPortField
    • Added NodeEditor.GetBodyStyle
    • Major InstancePortList rework (now uses ReorderableList)
    • Fixed deleting nodes on mac
    • Performance improvements
    • Various bugfixes
    As always, the asset store has a 10$ price tag. But xNode is available for free on GitHub.
     
    zyzyx likes this.
  35. tmcgillicuddy

    tmcgillicuddy

    Joined:
    Jul 8, 2014
    Posts:
    6
    Thanks for getting back to me!
    I'm building a mission objective manager, where there are stage nodes, that have a list of objective nodes. Once all the objectives are complete, it goes to the next stage node until it reaches the end. There are a variety of objective types, so different types of objective nodes are derived from the base objective node class.

    Whenever I open the project the final stage node is disconnected from the end node (these are two different types of nodes but the ports are of the same type).

    There is also a "ghost" objective node on that final stage node that my system tries to check when running through it seeing if the win conditions have been met. Clearing the port instances fixes this.

    Another stage has an objective node that all together disappears (no visual, no reference), then when I the game in play mode once or twice it pops back with all the references setup.

    What's worst though is that even when I fix the node connections and it all runs smoothly in the editor, when I go to make a build, the connections seem to no longer work. I can only speculate that the connections were broken again.
     
  36. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    I can't recreate this on my end. Can you send me a project with a reproducable bug?
     
  37. tmcgillicuddy

    tmcgillicuddy

    Joined:
    Jul 8, 2014
    Posts:
    6
    I found out that because the end node wasnt derived from the stage node, and the stage node was connected to the end node via a port looking for a stage node, whenever the graph would load in it breaks.
     
  38. zakrzus1

    zakrzus1

    Joined:
    Jan 31, 2015
    Posts:
    9
    Is there any unique id (not an instance id) which i can use to connect (via script) to another node?
    Or just is there any way to connect nodes via script?
     
  39. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Yes you can use nodePort.Connect(other node port)
    You can get nodePorts with node.GetPort(fieldName)
     
  40. neuroGear

    neuroGear

    Joined:
    Nov 25, 2012
    Posts:
    8
    Great system so far. Just started playing with it and it's quite simple to use. I like the way scriptable objects work as node types.

    Also there is a warning message in console, so just pasting it in here. I am using 2018.3.0b9.

    Code (CSharp):
    1. Unity has changed around internally. Can't open properties through reflection. Please contact xNode developer and supply unity version number.
    2. UnityEngine.Debug:LogWarning(Object)
    3. XNodeEditor.NodeEditorWindow:OpenPreferences() (at Assets/xNode/Scripts/Editor/NodeEditorReflection.cs:147)
    4. XNodeEditor.<>c:<ShowGraphContextMenu>b__52_0() (at Assets/xNode/Scripts/Editor/NodeEditorGUI.cs:149)
    5. UnityEditor.GenericMenu:CatchMenu(Object, String[], Int32)
     
  41. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    Glad you like it :)

    That error has been fixed in the git repo. Happens on 2018.3 and above.
     
    Last edited: Nov 13, 2018
  42. zakrzus1

    zakrzus1

    Joined:
    Jan 31, 2015
    Posts:
    9
    I'am also thinks that is great system :)
    Do you plan to add graph auto-layout function?
     
  43. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,643
    I wonder how hard would be to adapt this code to use the run time unity UI and be able to show the editor in a game instead of the unity editor.
     
  44. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    Quite tedious, imo. It would pretty much need an entire rewrite as far as I can tell. But don't let me stop you. I've seen some great things achieved solely through passion and guts. Good luck. :)
     
  45. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    I got that working in my Node Editor Framework, although much of it is just replacing editor-only controls.
    Since xNode and Node Editor Framework take quite different design aproaches, I would recommend not to make a decision solely based on runtime support alone. Do consider though that xNode is especially designed to keep the GUI and the runtime separate, so modifying xNode might be tricky (not sure though). If you try, here are some references that might help:
    - RTEditorGUI reimplements some generic editor-only controls
    - OverlayGUI reimplements the context menu (and could be extended to dropdowns, etc, too)
    And the rest is heavily dependant on the framework itself.
    Also, don't forget your I/O. If you plan to save at runtime, you'll also need a seperate format (like XML).
    Seneral
     
    sebas77 and Siccity like this.
  46. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    There is an example here showcasing how nodes can be edited through a runtime GUI like UGUI. However what it is, is basically re-implementing every control which is a very tedious and manual process.

    Assuming Seneral's Node Editor Framework is built on and only officially supports IMGUI (please correct me if I'm wrong)

    If you're fine with using IMGUI I'd recommend to use Seneral's instead of xNode.
    If you're set on a specific system like UGUI or NGUI, you're going to have to re-implement most if not all controls yourself.
     
    Seneral and sebas77 like this.
  47. Onebenarmy

    Onebenarmy

    Joined:
    Jun 22, 2016
    Posts:
    5
    Hey and thank you for xNode. Im building a 3D visual scripting tool for Virtual Reality for a University Project. Do you think its possible/makes sense to separate the whole visual xNode part from the logic behind it and use my own 3D visual representation of the nodes? how would you go about separating the two?
     
  48. Siccity

    Siccity

    Joined:
    Dec 7, 2013
    Posts:
    255
    It's definitely possible, but not where xNode's strength lies. You can check out the example I linked in my previous post, which does exactly what you're asking :)
     
  49. Rispat-Momit

    Rispat-Momit

    Joined:
    Feb 14, 2013
    Posts:
    266
    Hi there!!!

    Thank you for sharing! :D Is there any tutorial on how to use this tool? I can't find the window anywhere! The only thing I can do is to generate 2 scripts. A node and a nodeGraph.
     
  50. Rispat-Momit

    Rispat-Momit

    Joined:
    Feb 14, 2013
    Posts:
    266
    I figure it out! :p But you really need to make a tutorial!!! :D I am looking forward to donating :):):)
     
    Siccity likes this.