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. kaamos

    kaamos

    Joined:
    Aug 6, 2013
    Posts:
    48
    Oh damn, That is awesome, thanks so much! I've spent the last week working on a pretty flawed implementation of my own, and this pretty much saves the day. Huge gratitude to you for this.
     
  2. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    This project is so awesome.
     
  3. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    I'm trying out the changes Seneral made for the run-time compatibility. When I try to build to a Windows standalone I get this error:

    Assets/Plugins/Node_Editor/Framework/NodeEditorWindow.cs(2,7): error CS0246: The type or namespace name `UnityEditor' could not be found. Are you missing a using directive or an assembly reference?
     
  4. kaamos

    kaamos

    Joined:
    Aug 6, 2013
    Posts:
    48
    Same issue here
     
  5. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    I'm currently working on it! Actually it is fixed, but I try to fix a few GUI issues when building atm. Expect to update in ~hour :)
     
  6. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Committed an update, now it allows for builds! Unfortunately I had to restructure alot to do that, but now you have a runtime NdoeEditor! Popups still not working, not even in play mode, working on that next! :)

    Try out this windows standalone built with the calculation canvas example opened!
     
    kaamos likes this.
  7. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,355
    Nice!

    Noticed a bug right away, though; if you're running at a different resolution from your monitor, selecting the things that you want becomes really hard. Moving nodes is doable, but changing values in input nodes or changing the edges becomes near impossible.

    This was running in 1024 X 768 on a 1920x1280 monitor - the app thought that my mouse was far to the right of where it really was. Probably using 0-1920 coordinates from Input.mousePosition on a GUI element that's 0-1024 big.
     
  8. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Not good:( I'm currently using Screen class, so there might be the problem. Have to try a bit... If you set it to windowed it works though.
     
  9. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    I'm still getting the same error "UnityEditor could not be found'. I created a new project and downloaded the repo again and there's no change.

    I'll look through the code to see if I can find the issue :D

    It occurs at:
    Assets/Plugins/Node_Editor/Editor/Node_Editor/NodeEditorWindow.cs(2,7): error CS0246
     
  10. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    I guess I spoke too soon. Sorry for the spam. I was having trouble getting the folder structure working. The version Seneral posted works: after cloning the github you have to move Node_Editor into the plugins folder and then everything works!!
     
  11. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Wow! That was one bulk of a work:

    A custom GenericMenu! Exactly the same 'API' as the editor one, customisable, looks sweet, what do you need more? Requires to call GenericMenu.DrawActive () in the space the mouse position is in (here simply the DrawCanvas function;) ) though. Another step forward to a fully functional runtime Node Editor!

    Edit: For those who don't know, they're used for context clicks;)
     
    Last edited: Sep 6, 2015
  12. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Additionally, I guess it's time for a uniform GUIStyle. I'm not a GUI nor texture artist, but I try my best. Simple buttons which resemble the pro skin, how about that? :) If anyone of you is capable of doing it better and feel like contributing, you're welcome;)
     
  13. kaamos

    kaamos

    Joined:
    Aug 6, 2013
    Posts:
    48
    I found what may be a bug in the new runtime editor you just pushed... the line/curve drawing for the graph edges works fine if the editor is attached to a camera that's active when play mode starts, but if you attach it to another camera and activate that camera at some other point as say a triggered event, for example, the lines are no longer drawn (although you can still connect nodes).

    So in other words:

    Add two cameras to a scene
    Attach the runtime script to one camera
    Disable that camera
    Make sure the other camera is enabled
    Play mode
    Disable the current camera
    Enable the other camera with the runtime script attached
    Observe no edges are drawn, though somehow you can still connect nodes.
     
  14. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    strange... don't know about that straight away, but I'm using the GL class. I'll check tomorrow if there are any known issues like that with it.
     
  15. kaamos

    kaamos

    Joined:
    Aug 6, 2013
    Posts:
    48
    This might be a slightly more painful issue to correct since at least as far as I've seen, it causes no warnings or errors.
     
  16. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    Nice job on the runtime menus Seneral. I'm excited to try it out later.
     
  17. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    Did you commit the generic context menu?
     
  18. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Not yet, as I was still figuring why the group popup texture isn't shown xD I'll do a commit this evening.
     
  19. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    Okay cool :)
     
  20. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Committed the update, everything working regarding the GenericMenu! Also added a test button;)
     
  21. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    I downloaded it again into a fresh project and got a few errors. AALine.png and expandRight.png are missing.

    upload_2015-9-7_12-35-48.png
     
  22. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Dammit, I updated in a rush to get back to work, I must have deleted them along with their metas:(. I fixed that and also made seperators in the menus work.
     
  23. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    The generic context menu looks awesome! I made my first (very small) addition to the project. I modified the expandRight.png file so that it will look just like the one Unity uses.

    I tried to commit the changes to the master branch but it said access is denied. I also tried to create a new branch and that failed too. I've never added to someone else's project before. Any advice? :D
     
  24. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Didn't used Github before neither, thats why Baste has setup the repo;) You have to create a pull request, that's all I know lol
     
  25. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    I tried to create a pull request to add an empty file "TestDocument.txt". Could you merge the changes just so I know that it worked?

    If it works I'll add my expandRight.png as another pull request :D

    Thanks!
    Evan Daley
     
  26. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Yes it was correct
     
  27. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,355
    Using pull requests is a bit more of a hassle than just letting people commit, but just letting people commit FROM WHEREVER ON THE INTERNET gets a bit messy.

    Open source is not complete anarchy.

    The name pull request is a bit confusing at first, as you usually think of putting your stuff on a server as pushing. But the name tells you exactly what you're doing; you're saying "hey, I've made a change, I think you should pull that change into the main project". The people running the project can look at your change, and accept it if they feel like it's a good idea, and reject it if not.

    It's pretty neat.
     
  28. thehen2

    thehen2

    Joined:
    Apr 1, 2014
    Posts:
    43
    I'm getting a bunch of errors unfortunately (5.0.0f4):

     
  29. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Then your most likely missing the Node.cs file, please check that.
     
  30. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    Thanks for the clarification Baste.

    Now that I can make commits and pull requests hopefully I can find a way to contribute to architecture. :):)

    If anyone wants to add something and needs info on creating pull requests this is a good tutorial:

    http://kbroman.org/github_tutorial/pages/fork.html

    It looks confusing at first but it's really straightforward and easy once you understand it.
     
  31. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    I added a new texture for the "expandRight.png" folder marker. Its not a huge change but I'm proud of it. :D
     
  32. SniperEvan

    SniperEvan

    Joined:
    Mar 3, 2013
    Posts:
    161
    Since we are leaving the EditorLayout class behind its a little harder to draw and scale textures inside a node. This is my solution for scaling:
    upload_2015-9-8_19-50-45.png 0

    upload_2015-9-8_19-57-37.png

    Here's the code for this specific node.
    Github Link

    Logic:
    I check where the current GUILayout position is and then use GUI.DrawTexture in that spot with texture scaling applied. Then I call GUILayout.Space(100 * scale) to move the "gui layout cursor" down so we can add another label in the correct spot.

    Resizing the image preview expands the whole node.
     
  33. chai

    chai

    Joined:
    Jun 3, 2009
    Posts:
    82
    This is really awesome, I much prefer a custom lightweight node editor that does exactly what I need it to !

    Show clicked nodes directly in inspector
    Scriptable objects seems to be the best way to approach & store nodes (and optionally trees)
    Here's a handy way to show a node in inspector, stick somewhere in your OnGUI ()



    Code (csharp):
    1.  // Store last hovered node
    2. Event evt = Event.current;
    3. mousePos = evt.mousePosition;
    4. bool hovered = false;
    5. for(int i=0; i< nodes.Count; i++) {
    6.    if(nodes[i].rect.Contains(mousePos)) {
    7.      hoveredNode = nodes[i];
    8.      hovered = true;
    9.      break;
    10.    }
    11. }
    12.  
    13. // Show clicked SO node directly in inspector
    14. if (evt.button == 0 && !makeTransitionMode) {
    15.     if(evt.type == EventType.mouseDown) {
    16.  
    17.   if (hovered) {
    18.     Selection.activeObject = hoveredNode;
    19.   } else {
    20.     Selection.activeObject = null;
    21.   }
    22. }
    23.  
     
    Last edited: Sep 9, 2015
  34. chai

    chai

    Joined:
    Jun 3, 2009
    Posts:
    82
    Load node tree by simply clicking project asset (ala mecanim)
    A big bug you are all probably aware of by now, is that storing nested scriptable objects via AssetDatabase.AddObjectToAsset, nests them in an odd way (more about it here)
    Seneral has good example how to save/load assets like this, look it up page 1.
    But I wanted it to work like mecanim, e.g. just click an asset in project and it will autoload to node editor



    Code (csharp):
    1. void LoadNodeCanvas (string path) {
    2.  
    3.   // ... Look up Senera1 examples
    4.  
    5.   treeAssetPath = path;    // If load is successful store the path
    6. }
    7.  
    8. void Update () {
    9.  
    10.   // Don't update unless editor is open (replace with your own method)
    11.   if (editor == null)
    12.     return;
    13.  
    14.   // Ignore any object types except tree/canvas
    15.   // Note this does not include actual group containers (not objects)
    16.   Object sel = Selection.activeObject;
    17.   if (sel != null)
    18.     if (sel.GetType () != typeof(YourTreeType))
    19.       return;
    20.  
    21.   // Get path to selected object, guid supports even empty containers
    22.   if (Selection.assetGUIDs.Length == 0)
    23.     return;
    24.   string guid = Selection.assetGUIDs[0];
    25.   string path = AssetDatabase.GUIDToAssetPath (guid);
    26.  
    27.   if (path != treeAssetPath) {
    28.     LoadNodeCanvas (path);      // Attempt to load it, abort if not valid
    29.     Repaint ();     // Needed for loading externally
    30.   }
    31. }
     
    Last edited: Sep 11, 2015
    UnLogick likes this.
  35. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    @chai Great, but the active Node already gets selected in the project panel. Still cool to load a Canvas by clicking on it, I'll add that :)

    @SniperEvan That's too complex, isn't it? Nodes should be kept simple and easy, but you're right, layouting with providing a rect for each node is a pain. Problem is, BeginVertical cant be created at a specific position.

    I might have found a way to hack into the layouting system to get greater control over it. Key is the UnityEngine.GUIClip.s_GUIClips stack which contains all groups in a hierarchy. That could allow me to gain full control over the scaling system and give the ability to draw a canvas inside a group:)
     
    Last edited: Sep 9, 2015
  36. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    What do you think about something like that for the GUI:

    Is something in that direction suitable? This is just a quick test, but it could become the standard skin for NodeEditor.
    I implemented it that way that the default skin gets replaced when drawing the Canvas, so no need to modify existing stuff to use custom styles:)
     
    AhrenM likes this.
  37. chai

    chai

    Joined:
    Jun 3, 2009
    Posts:
    82
    @Seneral : tbh I wouldn't worry too much about it, imo the whole point of this thread is to get ideas/references to build our own barebone node editor.
    Which btw your script was probably the best help for this, thanks a lot mate !
     
  38. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    There are problems with the GUI being alot bigger in playmode which extends over the given Node rect, so I decided to atleast make a uniform GUISkin. You can see what I mean when you load the texture example I gave before in this thread, were that gets really obvious.
     
  39. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    To make a quick status report, I'm working on making DrawCanvas work in groups, aswell as nested inside other canvases. That's really hard to accomplish with scaling, as the clipping rects get screwed up, and alot of manual work is needed.

    Anyways, I got it working by hacking into the grouping system, reading the current group stack, leaving all groups, performing the drawing and recreating the groups again, all using Reflection.
    NodeEditor in groups work perfectly fine now, fortunately, and I currently track down issues regarding input in nested canvases:)

    I have to say I'm proud of that success, because afaik there's never been a proper scaling solution like that on the Unity forums before (atleast I didn't found it, and I searched hours)! :)
     
    manpower13 and UnLogick like this.
  40. chai

    chai

    Joined:
    Jun 3, 2009
    Posts:
    82
    Ye scaling is really tricky, hell when you think of it even mecanim doesn't support it !

    Have you had any luck selecting multiple windows ? (e.g. selection rectangle)
    It's pretty obvious how to tediously do it manually, but surely there's a way using native OnGui tools ?
     
  41. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    That was on my plan, actually. But I don't know a better solution than simply iterating through the nodes and check the selection rect, it's really straightforward I guess:)
     
  42. chai

    chai

    Joined:
    Jun 3, 2009
    Posts:
    82
    Ye, but that probably means we couldn't use GuiDragWindow and will have to write our own function right ?

    Btw you got some absolute paths in your code mate, which i suspect will break the code if someone dragged the folder
    On my editor I did relative paths something like this ;)
    Code (csharp):
    1. Object script = MonoScript.FromScriptableObject( this );
    2. string path = AssetDatabase.GetAssetPath( script );
    3. path = path.Substring (0, (path.Length - script.name.Length - 3) );
     
  43. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    Actually, NodeEditor does use a custom windowing system including dragging;) But with the dafault one, I do not know how to receive the dragged rect back:/

    Yes I have absolute paths and already use what you are proposing for checking if it's inside. Thats because you should install it in the Plugins folder, as it's a plugin, right? But I'll add it nevertheles:)
     
  44. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    I committed an update isolating the GUI styles to a seperate class and adding group scaling support in the file "GUIScaleUtility".
    It contains my complete solution I researched over the past week which enables correct scaling as the main feature:) It's made for being used in other tools, too:)
    Note though that it requires you to offset your controls by the Vector2 returned by the function in order for them to correctly scale to the pivot specified. You can optionally enable automatic shift for GUILayout controls for them to work immediately:)

    I'm really happy about that, may even be posting about that seperately as it's a common problem in Unity GUI.
     
  45. DiRoll

    DiRoll

    Joined:
    Jan 5, 2014
    Posts:
    32
    Seneral, I noticed that after creating the Input Node and entering Value wherever I clicked, the input field does not lose focus.
     
  46. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    A little bug in the custom float field I developed for runtime compability, I deployed the fix just now:)
     
  47. DiRoll

    DiRoll

    Joined:
    Jan 5, 2014
    Posts:
    32
    If I want to use int field, toggle or some other field in my custom node should I use EditorGUILayout.IntField or I need to add new field to GUIExt? (I doubt that I could write the code, for example, for toggle:()

    Bug
    When zooming tooltip is shown in wrong place

    I like this project and I will help to find bugs, suggest features.
     
    Last edited: Sep 30, 2015
  48. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    This bug is Unity's fault, because of their S***ty Scaling support... That's why I plan to replace the tooltip if possible aswell as Dropdowns (similar to existing context menu) which has the same problem.

    As to your Node GUI - you can use EditorGUI, of course, but if you plan to support both Editor and Runtime you cannot use it. As I want the example node to be supported by both and I want it to be an example I used my custom version.
    It's really a problem on Unity's side:(

    I should really make a list of known bugs and explanations on why they still exist;)
     
  49. KeldorKatarn

    KeldorKatarn

    Joined:
    Oct 30, 2013
    Posts:
    53
    What were the reasons again why you implemented your own window system instead of GUI.Window? Problems with dragging? Problems with the render order of the connection pins?
     
  50. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,185
    More control, simply as that;) In the current version this is not fully used, though. You can use custom styles in the default windowing system, too. But if you want to accomplish something completely different, like substance's nodes or even those from mecanim, you're completely lost:( There's really no disadvantage over the default system besides the lack of the default skin.

    I was thinking of moving that system (it's just the short function DrawNode) as a virtual function to Node, so you can have nodes that look completely different by overriding DrawNode:)