Search Unity

  1. Unity 2019.2 is now released.
    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,185
    Hi Suimisu,

    We're actually not too far away from that, though there are still some things to do. The GUI dependancies are mostly out of the way (Alternative curve function needs improvement so it works with scaling for example).
    Of course, there's still just the Editor window, but it shouldn't be hard to setup that in you ingame GUI code.
    Major problem so far is, unfortunately, that it requires you to start off without any grouping! That's because of scaling and Unitys clipping system, but we our hands are, afaik, bound on that part :(

    -> Current state on ingame node editor: If you can spare the zooming function, it should most probably work fine:)

    Regarding processing the data, you can simply do that by loading in the canvas and call the calculate functions, then read out the values. I'm working on marking values as paramters or output values which can be accessed more easily.
     
  2. Suimisu

    Suimisu

    Joined:
    Aug 2, 2015
    Posts:
    3
    Hey Seneral,

    That sounds great. I will look into integrating it in the project. Should be good enough for prototyping so I don't care so much about zooming at the moment. Thanks for your fast reply.

    Greetings,
    Suimisu
     
  3. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Cool! We would appreciate it if you share your ingame-GUI on the Github project;)
     
  4. Suimisu

    Suimisu

    Joined:
    Aug 2, 2015
    Posts:
    3
    Sure, I will report if or when I get it working :)
     
  5. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    I'm sorry but I missed one important thing: You can't create new canvases. Atleast for now! ScriptableObjects can only be serialized in the editor, but using an external serializer might work (This one sounds promising).
    And as we also annot just use a file explorer for resources, it's probably better to save everything by default to Documents/Appdata/ProgramPath/whatever...

    EDIT: UnityEditor.GenericMenu needs to be replaced, too. Perfect situation to implement a custom one which stands scaling;)

    Also: I just implemented a fully-featured curve and line drawing functions that works out-of-editor. Great!

    Additional Note:
    To support both statemachines and calculation canvases in the future aswell as controlling gui appearance I thought of handling everything with preprocessor directives, like NODE_EDITOR_LINE_CONNECTION which I just implemented and controls the connection type (line/curve). I hope this will provide enough flexibility;)
     
    Last edited: Aug 3, 2015
  6. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Just updated the repo with an event system and finally reworked the docs.

    @Baste Regarding your example of RoadNetwork stuff, that's now easily possible using the Event system. Quick example:

    RoadNetwork.cs
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class RoadNetwork : MonoBehaviour {
    5.  
    6.     public Transform[] cities;
    7.     public Road[] roads;
    8. }
    9. [System.Serializable]
    10. public class Road
    11. {
    12.     public int startCity;
    13.     public int endCity;
    14.     public Road (int start, int end)
    15.     {
    16.         startCity = start;
    17.         endCity = end;
    18.     }
    19. }
    RoadNetworkInspector.cs
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEditor;
    4. using System;
    5. using System.Linq;
    6. using NodeEditorFramework;
    7.  
    8. [CustomEditor(typeof (RoadNetwork))]
    9. public class RoadNetworkInspector : Editor
    10. {
    11.     RoadNetwork roadNetwork;
    12.     NodeEditorWindow editor;
    13.     public void Awake ()
    14.     {
    15.         roadNetwork = (RoadNetwork)target;
    16.     }
    17.  
    18.     public override void OnInspectorGUI ()
    19.     {
    20.         DrawDefaultInspector ();
    21.         if (GUILayout.Button ("Load Node Editor"))
    22.             LoadEditor ();
    23.     }
    24.  
    25.     public void LoadEditor ()
    26.     {
    27.         NodeEditorWindow.CreateEditor ();
    28.         editor = NodeEditorWindow.GetWindow<NodeEditorWindow> ();
    29.         editor.NewNodeCanvas ();
    30.         NodeEditor.curNodeCanvas = editor.mainNodeCanvas;
    31.         NodeEditor.curEditorState = editor.mainEditorState;
    32.         NodeEditor.checkInit ();
    33.  
    34.         for (int cnt = 0; cnt < roadNetwork.cities.Length; cnt++)
    35.         {
    36.             Transform city = roadNetwork.cities [cnt];
    37.             CityNode cityNode = NodeTypes.getDefault<CityNode> (); // Find default instance
    38.             cityNode = cityNode.Create (new Vector2 (city.position.x, city.position.z) * 50) as CityNode;
    39.             cityNode.InitBase ();
    40.             cityNode.city = city;
    41.             cityNode.name = city.gameObject.name;
    42.         }
    43.         for (int cnt = 0; cnt < roadNetwork.roads.Length; cnt++)
    44.         {
    45.             Road road = roadNetwork.roads [cnt];
    46.             Node StartNode = NodeEditor.curNodeCanvas.nodes [road.startCity];
    47.             Node EndNode = NodeEditor.curNodeCanvas.nodes [road.endCity];
    48.             StartNode.CreateOutput ("Road Out", "Road");
    49.             EndNode.CreateInput ("Road Int", "Road");
    50.             Node.ApplyConnection (StartNode.Outputs [StartNode.Outputs.Count-1], EndNode.Inputs [EndNode.Inputs.Count-1]);
    51.         }
    52.  
    53.         if (NodeEditorCallbacks.OnMoveNode != OnMoveNode)
    54.             NodeEditorCallbacks.OnMoveNode += OnMoveNode;
    55.     }
    56.  
    57.     public void OnMoveNode (Node node)
    58.     {
    59.         CityNode cityNode = (node as CityNode);
    60.         cityNode.city.position = new Vector3 ((cityNode.rect.position.x - NodeEditor.curEditorState.panOffset.x) / 50,
    61.                                              cityNode.city.position.y,
    62.                                              (cityNode.rect.position.y - NodeEditor.curEditorState.panOffset.y) / 50);
    63.     }
    64.  
    65. // Use other Events like OnRemoveConnection, OnAddConnection, OnAddNode, ....
    66. }
    67.  
    CityNode.cs
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System;
    4. using NodeEditorFramework;
    5.  
    6. [Node (false, "City Node")]
    7. public class CityNode : Node
    8. {
    9.     public const string ID = "cityNode";
    10.     public override string GetID { get { return ID; } }
    11.  
    12.     public Transform city;
    13.  
    14.     public override Node Create (Vector2 pos)
    15.     {
    16.         CityNode node = CreateInstance<CityNode> ();
    17.      
    18.         node.rect = new Rect (pos.x, pos.y, 100, 100);
    19.         node.name = "City";
    20.      
    21.         return node;
    22.     }
    23.  
    24.     public override void NodeGUI ()
    25.     {
    26.         GUILayout.BeginHorizontal ();
    27.         GUILayout.BeginVertical ();
    28.      
    29.         foreach (NodeInput input in Inputs)
    30.             input.DisplayLayout ();
    31.      
    32.         GUILayout.EndVertical ();
    33.         GUILayout.BeginVertical ();
    34.      
    35.         foreach (NodeOutput output in Outputs)
    36.             output.DisplayLayout ();
    37.      
    38.         GUILayout.EndVertical ();
    39.         GUILayout.EndHorizontal ();
    40.      
    41.     }
    42.  
    43.     public override bool Calculate ()
    44.     {
    45.         return true;
    46.     }
    47. }
    48.  
    49. public class RoadType : ITypeDeclaration
    50. {
    51.     public string name { get { return "Road"; } }
    52.     public Color col { get { return Color.green; } }
    53.     public string InputKnob_TexPath { get { return "Textures/In_Knob.png"; } }
    54.     public string OutputKnob_TexPath { get { return "Textures/Out_Knob.png"; } }
    55.     public Type InputType { get { return null; } }
    56.     public Type OutputType { get { return typeof(RoadValue); } }
    57. }
    58.  
    59. [Serializable]
    60. public class RoadValue
    61. {
    62.     [NonSerialized]
    63.     public float length;
    64. }
    65.  
    Seneral
     
    Last edited: Aug 5, 2015
  7. winxalex

    winxalex

    Joined:
    Jun 29, 2014
    Posts:
    143
    That isn't correct.
    Screen Shot 2015-08-07 at 12.49.28 PM.png
    Screen Shot 2015-08-07 at 12.49.23 PM.png I couldn't see that I've use reflection anywhere.
    GraphGUI and Graph are public and you have full control. You could subclass abstract GraphGUI and create your own.
    You could see how Mecanim nodes are done by looking code of UnityEditor.Graphs.AnimationStateMachine
    Yes If you are lazy and want same as Mecanim Editor look you can use reflection. You not need to reinvent the wheel.
    I really waste time to draw GL lines myself as it is 21st century.
    All the assets are pre 4.6 or they didn't want to depend of Unity for integration to there own tools VS or else outside or else....
     
  8. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Sorry, I got these information from here, which is basically the only source on that namespace out there... That's because even if we can use it, we have no documenation for it and it would be a huge pain using it I guess. Is there any extension using that namespace successfully?
     
  9. Nederseth

    Nederseth

    Joined:
    Sep 18, 2013
    Posts:
    4
    Hello everyone,

    Thank you very much for all your hard work!
    One month ago, I downloaded the Node Editor on the GitHub repository and since, I have been adapting it to the needs of my game project.
    Now that the bulk of the work seems to be done, I decided to share (see attached package).

    My tool is more or like a very small and specific UE4 blueprint system.
    You create your nodes in Edit mode and then you play them in Play mode.

    Because I won't use the GUI on runtime, I decided to split the system into two parts:
    - The editor part (all the code related to the Editor and the GUI) that won't be in the build of my game
    - The runtime part (all the code related to the behaviour of the nodes) that will be used in my game

    Feature List:
    Edit Mode / Window
    - Custom editor windows can be created
    - Editor windows can be used simultaneously
    - Editor windows can have their own nodes
    Edit Mode / Nodes
    - Nodes can be created by right-clicking on the canvas (only nodes that have a "path" pin will be available)
    - Nodes can be created by dragging a link from a pin (output as well as input) of an existing node (only "appropriate" nodes will be available, depending on the pin type)
    - Pin connections can be broken by right-clicking on the pins
    Play Mode / Nodes & Canvas
    - Canvas can be played by right-clicking on their nodes (which will become the start nodes)
    - Canvas can be paused, resumed or stopped by right-clicking on them
    - Canvas can be played simultaneously

    In the attached package, I put two examples of editor windows (see the "Node System" menu) in which there are examples of canvas and nodes.
    Have fun!

    Unfortunately, I haven't taken the time to write a documentation.
    I hope the examples will help you to understand how all this works.


    Now, as I am not an expert in programming (still a lot of things to learn!), there may be bad design, bad code or mistakes.
    Do not hesitate to tell me if there's anything wrong!


    Hope you'll find it useful,
    Nederseth
     

    Attached Files:

  10. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Looks fantastic!
    Some of your implementations are very handy and the editor does look really good:) Unfortunately there's a month between your implementation and the Node Editor here, but I'd be great if you made a branch on the github repo ;). It has some disatvantages in the playmode implementation, but I really like the concept of mixing the statemachine and the calculation nodes seamlessly. Well done! :)
    And tbh, I'm too far from being a perfect programmer. I've started Unity including programming just about two years ago, whereas I've started programming the editor only about a year ago;)
     
  11. Nederseth

    Nederseth

    Joined:
    Sep 18, 2013
    Posts:
    4
    Thanks for your comment, Seneral.
    What are the disadvantages that you noticed in the playmode implementation? Can you elaborate so that I can improve it?
    I'll try to make a branch on the Github repository, I'll look first how to do that :). However, from now on, I will be more focused on my game project, so I will not be very active on my tool anymore.
     
  12. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    You seem to have two versions of the nodes, one for playmode and one for the editor, where the editor is basically a wrapper around the playmode node. Generally, alot of classes have such a seperate editor class, and I'm wondering why is that needed? Ripping of the GUI and other stuff from the runtime part limits the system to editor only...
     
  13. Nederseth

    Nederseth

    Joined:
    Sep 18, 2013
    Posts:
    4
    I see. I knew I should have written a small script to show an example...
    Well, you're half right :).
    All the classes that you will find in the "Editor" folders are indeed editor only. I don't want/need to create/see nodes outside of the editor.
    However, concerning the other classes, although they are used in the editor, they can also be used outside, by the "NodeSystem" class, which is basically a "player".

    A very basic example:
    Code (CSharp):
    1. NodeSystemData nodeSystemData = (NodeSystemData)Resources.Load("NodeSystem/Data/CalcEditor", typeof(NodeSystemData));
    2. // Play from the first node of the first canvas of the CalcEditor asset
    3. NodeSystem.Play(nodeSystemData.GetNodeCanvasList()[0].nodes[0]);
    EDIT: I just tested my example above in a monobehaviour script and realized that it wasn't working well in the Start function because of the "EditorNodeSystemModeHandler". I solved the problem and updated my package attached to my first message.
     
    Last edited: Aug 14, 2015
    Seneral likes this.
  14. vicenterusso

    vicenterusso

    Joined:
    Jan 8, 2013
    Posts:
    129
    This is awesome!

    I'm trying to tweak it a little to suit my needs but I'm having a few drawbacks:

    1) The node canvas is always "refreshing" and cleaning the canvas. After I hit stop on editor, it clears. I haven't seen this on Issues (github) so I don't know if it's expected or a known bug.

    2) What are transitions for (button with "#")? If it's a dummy connection for a later implementation, cool, so How do I get that info?

    3) What's the difference between transations and the connections made with the handlers?

    4) So here is my real problem to solve. I want to use this node editor for the following scenario: I have some objects that I want to link to others and I need several types of connections. For example, a Key to open a Door, or an Gem that gives the player 1000 coins. I want to link all that visually, and when the player interacts with the object (key or the gem) I want to search that canvas and see what it does and then take the necessary action. I think it's simple from a technical view.

    Anyway, I'm willing to contribute to the project but I need some kick :)
     
  15. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Hi vincent,

    To your first point, it seems to be a bug and I'll try to sort that out. As of now, the editor window isn't supposed to run in playmode (except if you take the version of Nederseth:)). I'll try to sort that out.

    The transitions are WIP, they're for a statemachine-type of editor. Basically, actual connections are for calculating the canvas in a glimpse of a second. The transition system is for "walking" a path, where there are conditions and triggers playing in. Hope that makes sense:)

    Actually, from what I understand, you can't really benefit from a node editor... To achieve that effetively, you'll need something completely different. Simply because there's not much to link, I assume.
    You could simply make scripts for that - or, if you want it visually, a generic window with a simple interface which has a system that allows you to call any function on any object. when an object is activated.

    Because: the problem is, you could make custom nodes for a key, door, gem, whatever - but doing these as simple scripts is much more efficient. And making links between as few as a key and a door - that's done easier with a simple object reference in a script.
    Hope you get my point:)
    But just assume you still want sth like that, you can query the node canvas at runtime for specific nodes which represents you key object and check the connection.

    Have fun and don't hesitate to contribute:)
    Seneral
     
  16. vicenterusso

    vicenterusso

    Joined:
    Jan 8, 2013
    Posts:
    129
    Hi!

    Tks for your reply :)

    Yes I can make it like simple custom editor and linking stuff from there. But the thing is, I will have hundreds of items linked between scenes (that I will make each scene a big prefab for easy linking). A practical example: Think a game like The Dig, a very complex game with a lot of items linked in a lot of ways. Basically what I need is a generic node (with a gameobject field) and a lot of custom type links. Then, retrieving this info somehow at runtime (or maybe having the node editor actually replicate all linking actions to the object into hierarchy) I can take necessary actions with only these information: the 2 objects and the relation between them.

    Hope you get my point too! :)
     
  17. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Ok, so your trying to link between objects in different scenes... I guess that can't be achieved neither by hand or by code without a custom system - But that's a different problem.
    And yes, a node wich can basically call functions and retrieve informations from classes and objects is really needed, both for statemachine and calculation purposes:)
    It's possible by getting an object ref and, when assigned, get every script on the object, provide the user with all script members (scan the assembly with reflection for that type, enuemrate through functions, methods, properties, etc.). Definetely possible - and VERY useful.
    Of course also with types and static members instead of an object. That means, we need procedural Inputs/Outputs. That is possible but I'm going to implement an easier solution for that.

    But currently I have not much time to work on anything, have a busy week:(
     
  18. vicenterusso

    vicenterusso

    Joined:
    Jan 8, 2013
    Posts:
    129
    Yea, that's why I said I will transform each traditional scene into a big prefab and make it all accessible through hierarchy for easy linking.

    And no, I'm not asking you to do anything :D I just want to make sure that this node solution can works for this type of thing I want to do...
     
  19. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Ok, now I understand. It'll be possible, but be aware: Currently there is a problem with huge canvases (because of auto-save and Unity having to reimport the whole asset when saving), so when it's a huge scene you'll probably experience wait times of around 5secs when creating or deleting nodes :(
    Other than that, you have two options: Use the WIP transition system so when calling activate on the object, query the canvas for the node and check it's transitions (in the center GUI you can add some things to perform with an enum or string identifier), or make appropriate connection types. Either way, you currently have some extra workaround involved...
     
  20. vicenterusso

    vicenterusso

    Joined:
    Jan 8, 2013
    Posts:
    129
    Got it! Going a little off-topic, do you have any experiencie with other node-system plugins like PlayMaker, uScript, etc? If so, is it possible to adapt one of them to my needs?
     
  21. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Unfortunately not, but I suppose so. First I'd check if they support custom nodes or have an existing solution...
     
  22. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    This node editor looks so cool! I plan on spending the next few days digging into the code. Would it be possible to pass arrays of values as inputs and outputs? And/or custom classes?

    Thanks!
     
  23. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    I've been reading the code and learning how to make simple nodes. As a test I created Int, Double, and Vector3 nodes with inputs, calculations, and outputs, based on your examples. I can post them if your interested but it's pretty basic. Seneral, in a previous post I see you had textures nodes! Would you mind uploading the source for the texture node implementation!?

    Thanks in advance!
    Evan Daley
     
  24. Mayer102

    Mayer102

    Joined:
    Aug 24, 2015
    Posts:
    3
    This node graph framework is great. Thanks Seneral. Keep up the good work!

    ps. I'm using u4editor and I made some improvements for input, to be more like in Blueprints. If someone were interested I attached changed files.
     

    Attached Files:

  25. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Cool! :) Yes it's possible by creating new ConnectionTypes

    It's pretty basic but I might do that. I'll add it to the github repo, ok?

    We can't use your contribution if we can't see what has changed and where;) You can submit it to the github repo and write a short summary of what you've done.
     
  26. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    So here's the texture nodes package:
    http://1drv.ms/1I8ExqP
    It contains the nodes of the screen I posted earlier and which I posted in the documentation.
    You can put it anywhere inside a project which contains the latest NodeEditor version - that's the benefit, it's completely independant and still works:)
     
  27. seldom

    seldom

    Joined:
    Dec 4, 2013
    Posts:
    111
    Relations inspector may be for you. It displays a graph of relations between objects (in your case GameObjects), supports multiple relation types and can interact with the game at runtime. You'd define all the specifics of your use case in a backend class and the tool will handle the rest. If you have trouble setting up your backend, I'm happy to help.
     
  28. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    Okay thanks Seneral. I'll check it out tonight!
     
  29. Mayer102

    Mayer102

    Joined:
    Aug 24, 2015
    Posts:
    3

    Maybe not big things (surely not;), but for me its much easier to using NodeEditor with this:
    - You can create connection from Output to Input (not only from Input to Output)
    - You can break connection using RMB on NodeInput or NodeOutput
    - When You are creating connection from In / Out to empty space - context menu with available nodes will always shows up (not only on RMB)
    - FIX: NodeInput & NodeOutput always shows on the middle on screen
     
  30. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Cool:) I'm unable to do anything atm so I appreciate contributions. But I think third isn't good because you still need the ability to cancel it...
    And the fourth problem should only arise if you do not call the Input/Output knob functions inside your GUI, in which case the positions remain default. Better to fix that;)
     
  31. Mayer102

    Mayer102

    Joined:
    Aug 24, 2015
    Posts:
    3
    Yes. You could cancel it using LMB or RMB on empty space. But when I make connection I almost always want make connection so its one click less :p

    I call Input/Output knob functions inside my GUI. I don't say they stay on the middle on screen, but only shows up there, and on next update move to proper position. It not look nice ;) Another instance of this bug is when you pan window: position of knobs is delayed one update to node position. Change render order fix the problem...
     
  32. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    With not good I mean impractical when you have two click twice to abort connecing:) And because of the render order, I choosed that order because I don't want the knobs to be drawn ontop. But in my current version, where I am working on the transitions, I switched the order to:
    Transitions, Nodes, Connections, Knobs
    Which essentially fixes that and is correct:) I just wasn't aware that the actual version on GitHub had it different...
     
  33. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    I've been experimenting with the Node Editor and I noticed that this happens:

    upload_2015-8-28_11-3-23.png
    [Import settings: Alpha from Grayscale Checked]

    At first I thought it was an error but then I discovered that it just depends on the texture import settings.

    upload_2015-8-28_11-4-9.png
    [Import Settings: Alpha from Grayscale Unchecked]

    Just thought it was interesting. Everything seems to be working nicely.

    On an unrelated note:
    I want to use this system to add textures to a terrain. Would it be possible to do this at runtime? Where would you start? I understand how to create the Texture2D objects and pass them as inputs and outputs -- but is it possible for the Node system to communicate with scene objects?

    ~E
     
  34. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Yes they can, just as a normal behaviour;) It would be probably the best for your case to have a global property panel at the right for the whole settings, like the terrain object, etc.

    Btw if you don't wan't the alpha set the alphaBlend parameter on GUI.DrawTexture to false
     
  35. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    Okay thanks Seneral.

    upload_2015-8-28_12-4-40.png

    Anyone else getting leaked objects? I probably broke it somehow with my custom nodes.
     
  36. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,330
    Leaked objects are a notorious problem with editor stuff. It should not crash the editor, though - I've got some editor scripts that are leaking meshes all over the place, and nothing bad happens.
     
    AhrenM likes this.
  37. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    True. If you ever experience this again and even are able to reproduce this, that'd be a great help to fix that:)
    I'm sure it's pretty hard to break Unity with custom Nodes, I suppose something in the framework or perhaps on Unity's side.
     
  38. vicenterusso

    vicenterusso

    Joined:
    Jan 8, 2013
    Posts:
    129
    You nailed it! Exactly what I want :D

    I see you haven't updated lately on github. Is is stable enough? Any known bug?
     
    Last edited: Aug 29, 2015
  39. AhrenM

    AhrenM

    Joined:
    Aug 30, 2014
    Posts:
    73
    Yeah, this one is fun. I've got large numbers of ScriptableObjects in Editor space and they leak like crazy every time I trigger an AppDomain reload. About to write a garbage collector just to keep things tidy.
     
  40. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    I'm sorry I didn't showed progress lately, but I have not much time to spend on continuing the transition If anyone wants to take it up and continue, that'd be good, I'll probably won't work on it for another week or so. Regarding the system as a whole, don't worry, it's stable and all working great, and I'll still fix any bugs that will arise:)
     
  41. vicenterusso

    vicenterusso

    Joined:
    Jan 8, 2013
    Posts:
    129
    Hey @Seneral my reply was address to @seldom :D:D
     
  42. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    :oops: Oops sorry
     
  43. seldom

    seldom

    Joined:
    Dec 4, 2013
    Posts:
    111
    Glad to hear it. Originally, this was a rule-set editor, as part of a geodata project. Like many others, I arrived at a node-based editor tool. Then I realized how often unity showed me one object reference, where actually I was interested in a chain or net or graph of those. Or I wanted to go the opposite direction and find everything that references a selected object. So I generalized the tool and added automatic layout, now I could drag any object into it and get a reference graph right away. Today it works with any kind of object and any kind of relation, with all the configuration code in a single class. I'm happy that it's useful for others too.

    For all I know it's stable, but so far I'm the only regular user and have done most of the testing. Once others are using it, I'm sure someone will find a way to blue-screen it :)
     
  44. kaamos

    kaamos

    Joined:
    Aug 6, 2013
    Posts:
    48
    How would I go about drawing a node canvas I've created and saved in the editor to the play mode gui canvas, for example?
     
  45. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    Hey guys. I've been wondering the same thing. How do we draw and adapt the node editor at runtime?
     
  46. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    I saw a previous post about the runtime not being able to create scriptable objects? We need some sort of external package to instantiate the nodes?

    I am fairly experienced with c# but don't really know anything about scriptable objects. With a little direction I could try to spearhead the charge and make the system work at runtime.

    Runtime support is really crucial if we are using this for a procedural system. For instance if we had a node system generating procedural terrain we need it to happen during gameplay!
     
  47. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    If you only need to calculate it at runtime, it's pretty simple. Just load in the canvas (has to be in resources) with NodeEditor.Load and use one of the calculation functions (CalculateAll, CalculateFrom,...).

    If you want the Node Editor GUI at runtime, there are some limitations you have to consider. First, note that although most GUI stuff works in Editor and GUI, there may be parts that do not appear correctly. A serious limitation so far is scaling: For that to work, you have to make sure you are not in any group, as far as I know. You can try though, but in case it's not possoble, you shoukd remove the scaling part (in DrawCanvas and Input).
    To draw it, look at the editor window first. It's nearly empty, all the GUI stuff is done by DrawCanvas. Just call it, then:)
     
  48. kaamos

    kaamos

    Joined:
    Aug 6, 2013
    Posts:
    48
    I'd certainly be interested in seeing a small practical example of what you described to get a simple minimal node canvas drawn in the play mode... zoom isn't so important in my case, just to load nodes, to allow them to be connected by the user, and to pass data dependent upon connection state.
     
    SniperEvan likes this.
  49. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Ok, I tried and made a script which loads and draws a canvas. it works! I had to modify the drawing function a bit to adapt better, works perfect now! I committed as an update because of multiple scripts being modified.

    The idea is like the following:
    Code (csharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections.Generic;
    4. using NodeEditorFramework;
    5.  
    6. public class RuntimeNodeEditor : MonoBehaviour
    7. {
    8.     public string CanvasString;
    9.     public NodeCanvas canvas;
    10.     public NodeEditorState state;
    11.  
    12.     private Rect rootRect;
    13.     public Rect canvasRect;
    14.  
    15.     public void Start ()
    16.     {
    17.         rootRect = new Rect (0, 0, Screen.width, Screen.height);
    18.         canvasRect = new Rect (10, 10, Screen.width-20, Screen.height-20);
    19.  
    20.         if (!string.IsNullOrEmpty (CanvasString) && (canvas == null || state == null))
    21.             LoadNodeCanvas (CanvasString);
    22.     }
    23.  
    24.     public void OnGUI ()
    25.     {
    26.         if (canvas != null && state != null)
    27.         {
    28.             NodeEditor.checkInit ();
    29.             if (NodeEditor.InitiationError)
    30.             {
    31.                 GUILayout.Label ("Initiation failed! Check console for more information!");
    32.                 return;
    33.             }
    34.  
    35.             try
    36.             {
    37.                 GUI.BeginGroup (rootRect); // One group is allowed only
    38.                 // NO other groups possible here!!
    39.                 state.canvasRect = canvasRect; // <- Canvas rect goes here
    40.                 NodeEditor.DrawCanvas (canvas, state, rootRect);
    41.                 GUI.EndGroup ();
    42.  
    43.                 // No root group
    44. //                state.canvasRect = canvasRect; // <- Custom rect comes here
    45. //                NodeEditor.DrawCanvas (canvas, state);
    46.             }
    47.             catch (UnityException e)
    48.             { // on exceptions in drawing flush the canvas to avoid locking the ui.
    49.                 NewNodeCanvas ();
    50.                 Debug.LogError ("Unloaded Canvas due to exception in Draw!");
    51.                 Debug.LogException (e);
    52.             }
    53.         }
    54.     }
    55.  
    56.     public void LoadNodeCanvas (string path)
    57.     {
    58.         // Load the NodeCanvas
    59.         canvas = NodeEditor.LoadNodeCanvas (path);
    60.         if (canvas == null)
    61.             canvas = ScriptableObject.CreateInstance<NodeCanvas> ();
    62.        
    63.         // Load the associated MainEditorState
    64.         List<NodeEditorState> editorStates = NodeEditor.LoadEditorStates (path);
    65.         if (editorStates.Count == 0)
    66.             state = ScriptableObject.CreateInstance<NodeEditorState> ();
    67.         else
    68.         {
    69.             state = editorStates.Find (x => x.name == "MainEditorState");
    70.             if (state == null)
    71.                 state = editorStates[0];
    72.         }
    73.        
    74.         NodeEditor.RecalculateAll (canvas);
    75.     }
    76.  
    77.     public void NewNodeCanvas ()
    78.     {
    79.         // New NodeCanvas
    80.         canvas = ScriptableObject.CreateInstance<NodeCanvas> ();;
    81.         // New NodeEditorState
    82.         state = ScriptableObject.CreateInstance<NodeEditorState> ();
    83.         state.canvas = canvas;
    84.         state.name = "MainEditorState";
    85.     }
    86. }
    basically it's the same as in the editor window. And scaling does work, but with one top-level group only, or none.
    Some stuff still isn't supported, like the popups, etc., but that's a problem that persisted ever since.

    To load the canvas, add the path to the component or assign NodeCanvas and NodeEditorState directly (expand your save file, where you'll find both).

    And there has to be a change in GUIStyle;)

    I'm happy to see this work, I didn't tried before:)
     
    SniperEvan and kaamos like this.
  50. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185

    Doesn't it look cool? :D
     
    Deon-Cadme and SniperEvan like this.