Search Unity

Simple node editor

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

  1. GamesDeveloper12

    GamesDeveloper12

    Joined:
    Nov 7, 2013
    Posts:
    18
    Hi,
    I have recently found this forum and the framework, how can i add a string as an input and output for a node. I have tried using:
    node.CreateInput("Name", "String");
    node.CreateInput("Name", "string");

    but i get an error saying "No TypeData defined for: String" for both options.

    I have added:

    public class StringType : ITypeDeclaration
    {
    public string name { get { return "String"; } }
    public Color col { get { return Color.cyan; } }
    public string InputKnob_TexPath { get { return "Textures/In_Knob.png"; } }
    public string OutputKnob_TexPath { get { return "Textures/Out_Knob.png"; } }
    public Type Type { get { return typeof(string); } }
    }

    to the ConnectionTypes underneath the FloatType class, but it still gives me the error. Do i need to add strings somewhere else, my understanding of the documentation is that adding the string type declaration should allow it to work but it doesn't.
     
    Last edited: Feb 17, 2016
  2. GamesDeveloper12

    GamesDeveloper12

    Joined:
    Nov 7, 2013
    Posts:
    18
    Solved, it was a simple misunderstanding as to what the input/outputs meant and how to add a field
     
  3. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Hi, cool you solved it:) There seems to be quite some misunderstandings regarding this, could you tell exactly what you struggled on so I can improve the documentation? :)

    I actually already set up the base yesterday, it isn't nearly as much work as I've expected it to be:) I could hand you in the basic structure so you can finish it and I can work on the implementation as a Node in the meantime, but I'm not sure it makes much sense now... It's generating a GenericMenu popup for the function selection, and it's nearly finished already...
    As I said before this is hard to split up as it's a very narrow field to do:( Would it be ok if I finish this including the Action node (which is not much to do from then, either) on my own?
     
  4. Kamigaku

    Kamigaku

    Joined:
    Mar 23, 2014
    Posts:
    25
    Hey Seneral, i hope you are progressing well on your MethodNode (or ActionNode, or whatever :)).
    On my side i'm done with Serialization and save/load. Right now i can save my function nodes, load them on the canvas and datas are save. I was considering trying to implement the "object" node pointing to a GameObject and fetching his methods but i will wait for your next push before doing something.
    I just have to had an entry and an exit point and i'm done with mine !
    I'll also wait for the next push to fit it better.
     
  5. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Hi, are you still following the model of fetching the functions from a class first? Then what I'm doing would be completely uninteressant:) Right now I'm figuring a way to store some commands as a collection, instead of individual functions. Also trying to make the UnityFunc generic, meaning to support for statics, etc. After I made the UnityFunc ready for the ActionNode I'll actually have something to push;)
     
  6. Kamigaku

    Kamigaku

    Joined:
    Mar 23, 2014
    Posts:
    25
    Yes i'm still, for the moment, fetching functions from a single class.
     
  7. ScriptGeek

    ScriptGeek

    Joined:
    Mar 4, 2011
    Posts:
    45
    Hi Seneral, I'm not sure I understand where you're at. I was looking into making a structure where new types of nodes are defined by inheriting from the Node class, just like now, but node subclasses would have the option to define a GUI method, which would be called after the side window GUI elements are drawn, but still inside this area (only if the currently selected node had this specific method definition). So essentially the implementation would work like the MonoBehaviour Awake, Start, and Update methods, where the methods are called only if they are defined. This would add functionality while avoiding breaking previously created node graphs. If you're working on a different approach for this I can sit out for this round of fun. Maybe there's something else I can work on?
     
  8. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Sorry for the unclear message, I mean the base of the UnityFunc GUI (Fetching methods with reflection and placing them in a GenericMenu wih apropriate execution calls so the node can work with that). Actually for the NodeProperties I would just take an empty virtual method which may be chosen to be overwritten by the Node Creator or not. Thats the easiest and fastest way.
     
  9. ScriptGeek

    ScriptGeek

    Joined:
    Mar 4, 2011
    Posts:
    45
    Oh I see, sorry for my confusion. Using a virtual method for the node properties would indeed be the easiest way to access the methods. This sounds like a good solution.
     
    Last edited: Feb 18, 2016
  10. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    I have been asked why I did not use the Issues system of Github to manage the progress, but instead created a document. That was a great question, honestly I didn't thought on that before;)
    It took an hour but I created a total of 11 new 'issues' from the Roadmap document, and improved it's content. It's way easier to talk about specific TODOs and such this way...
    @Kamigaku We better continue discussing the action node progress on the apropriate issue on the repo, so we don't 'spam' this thread with a specific topic;)
     
    Last edited: Feb 18, 2016
  11. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    For those unaware, there's currently alot activity on the GitHub repo:) For example we're establishing a new workflow called GitFlow and we've now also a html version of the documentation, avaiable on GitHub pages here:
    http://baste-raingames.github.io/Node_Editor/
     
  12. TiagoMartins

    TiagoMartins

    Joined:
    Mar 15, 2015
    Posts:
    12
    Hey guys, nice work you guys did around here, congrats!

    I'm planning to implement an editor tool to create action sequences, the idea is to make a state machine that executes actions/animations to form a cutscene

    I already saw here in the thread some code examples to implement a state machine, so this framework can't be too far off

    I tried to implement my idea using mecanim's StateMachineBehaviours, the problem is that:

    - In mecanim there's no way, out of the box, to evaluate if a behaviour has "finished" to do it's work in order do a transition
    - Assigning scene objects to animator behaviours, in a generic way, required developing a custom editor, which ended making the end result not very user friendly, since the user would have to switch between the scene viewer property inspector and the animator window)

    And some other minor problems

    Do you guys think that I would be better off with this node framework instead?
     
  13. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Hi Tiago!
    First off, this framework's State Machine is still in developement. It's the current focus though and we're close to finish it;)
    Second, I did not personally tried out the default StateMachineBehaviour. There may be features that this framework does not implement (yet) but atleast you have the freedom to implement them yourself or modify the framework in any other way you can imagine. To get a better overview of what this framework already supports you can take a look at the documentation.
    Last, you have to expect some minor problems with this aswell. But you can count on us that we'll fix any bug as fast as possible:)
    After finishing the Statemachine, we're open to any suggestions you may have, or any problems you may encounter, so we can cover up most use cases straight away;)
     
  14. TiagoMartins

    TiagoMartins

    Joined:
    Mar 15, 2015
    Posts:
    12
    Thanks @Seneral

    Yeah that's true, I'm not quite happy with the way that StateMachineBehaviour works at the moment, I believe it's still partly work in progress, so at some point it may meet my needs (or not)

    So anyway I was going to end up developing a state machine, and since this framework already has it, or partially, I think it's better than start from scratch to make a Node Editor, so I think I'm in the right place, I just wanted some other opinions of users that used both your framework and StateMachineBehaviour to get their thoughts on this.

    Possibly when I get home I will try to run the code and add some of my own, if I can I will gladly submit possible improvements :)
     
  15. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Cool! As a note, the major thing that holds of developement on the statemachine for now is that the transition conditions are not serialized yet (funcs). I already developed a solution (UnityFunc) and I'll soon make use of it in the transition conditions. I didn't even start yet generalizing the system. For not it's just one transitions with a timer and some callbacks, nothing more.
    What is to come: A dynamic Transition extension model similar to that of the Node or Connection Types, so you can have an AnimationTransition, AITransition, DialogueTransition, etc., all seperated from each other. Those types then have the control on what is happening with the transition. If you still find some things that don't quite fit your requirements, no problem, I can try to integrate them into the system;)
     
  16. TiagoMartins

    TiagoMartins

    Joined:
    Mar 15, 2015
    Posts:
    12
    Took some time to read the code, it's quite clear and there's lots of functionality in there

    Just a quick question, if I wanted to have a more dedicated tool, like the one I described above, where I just pretend to have Nodes of a certain type to show on the context menu, I would need to fork the library and change the code or did you guys thought about a more versatile way to do it?
     
  17. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Well, first off, you would only fork the repo if you would want to publish any modifications to the framework code you made which you could then creaet a pull request from to the main repo.
    If you just want to use it in your project you can use it locally of course.
    Regarding Node Implementation, there's a special system build so you can put a custom node class in the project and the framework would automatically fetch it and integrate it into the editor. Same with Connection Types, basically. Again, I'd refer to the documentation, especially the getting started section, which outlines the creation of a custom node;)
     
  18. TiagoMartins

    TiagoMartins

    Joined:
    Mar 15, 2015
    Posts:
    12
    Thanks for the feedback, will start make my changes to adapt to my project, and try to achieve what I want :)
     
  19. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Cool, let us know when you have something cool;)
    Don't recommend working with states / transitions yet though, you'd get more trouble than anything, promised;) We've a solution ahead already:)
     
  20. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,383
    While it is possible to use Unity's Animator Controllers together with StateMachineBehaviours to create proper state machines, the fact that it's created to run animations means that some of the functionality breaks down when there isn't any animations around.

    A dedicated state machine system will serve you a lot better. Last time I checked, the Node Editor is also able to zoom, which the Mechanim team still hasn't managed to implement hrglblrhfl.
     
  21. TiagoMartins

    TiagoMartins

    Joined:
    Mar 15, 2015
    Posts:
    12
    @Baste exactly, that's part of the workarounds that I would have to make, quite a shame that there's no other way to extend the animator's state machine has a lot of potential, but I can see all that potential being used with the framework from this thread, so no big issue :p
     
  22. fakegood

    fakegood

    Joined:
    Oct 11, 2013
    Posts:
    17
    Hello, @Seneral and @Baste, thanks for the awesome editor! :) however, i couldn't seem to run it due to multiple errors in some scripts from Framework folder. Is it possible that you guys prepare a .unitypackage file for easy integration? :)
     
  23. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Hi, I recently pushed a WIP update to the repo, so things might not be running as expected. That is really unfortunate and we already changed the way we manage the repo so the master branch only contains fully tested code.
    I'll get you something asap and will also push it to the repo asap so we have a working framework online.
    But afaik there shouldn't be issues, still, especially not on start up. Can you print them?
     
  24. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    I've built a cleaned release now which does not include any WIP stuff but is consiedered stable:)
    It can be found here.
    Please tell me if you're still experiencing problems!
     
  25. fakegood

    fakegood

    Joined:
    Oct 11, 2013
    Posts:
    17
    Thanks! It's working fine right now. Thank you very much! :)
     
  26. TiagoMartins

    TiagoMartins

    Joined:
    Mar 15, 2015
    Posts:
    12
    Hey guys, I was modifying the code and found an issue that you guys may be able to help me with

    There's this line of code in NodeTypes.cs:
    List<Assembly> scriptAssemblies = AppDomain.CurrentDomain.GetAssemblies().Where ((Assembly assembly) => assembly.FullName.Contains ("Assembly")).ToList ();

    But I was trying to remove what comes after .Where, because I have my solution divided into different projects, and I would like to create more specific nodes in separate projects

    That works fine, but after closing the editor the node information in the LastSession asset is lost, is there any limitation about having scriptable objects from different DLLs in one .asset file?
     
  27. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    I don't know of such limitation to the scriptable object but that doesn't mean it doesn't exist:)
    First off, what do you mean with 'remove what comes after', it won't work when you remove the node type fetching. You can try with replacing the line with
    Code (csharp):
    1. List<Assembly> scriptAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList ();
    so you'll be sure your node type in an external dll is included. Shouldn't change anything in how scriptable objects reference this type though:(
     
  28. TiagoMartins

    TiagoMartins

    Joined:
    Mar 15, 2015
    Posts:
    12
    Sorry, I didn't make myself clear but yes, that is the line of code I'm using

    Seems like if I create the same project it works fine, but if it ends in an external DLL it causes the problem, I'm going to play around it a bit more, if I can't handle it I can have all the nodes in one DLL is not the end of the world,

    Just wanted to know if you guys knew something more about this issue I'm having
     
  29. iddqd

    iddqd

    Joined:
    Apr 14, 2012
    Posts:
    403
    I just downloaded the latest version and have a small observation:
    It is no longer specified anywhere that the scripts need to be moved into the plugins folder - but I'm assuming that they still need to be there since there is some mention of the Plugins folder. Is there a reason why the scripts aren't inside a plugins folder in the github repo - so they are always at the correct place when imported?

    The current commit also has some errors, such as a duplicate NodeCanvas class definition ;-)
     
  30. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Thanks for the note, I seriously didn't noticed. Now even though I specified to delete them, both the redundant docs (odt and pdf versions) and the moved files weren't affected by the commit... Strange.
    And for record, the framework doesn't need to be in the Plugins folder anymore (since months now). It's just the default folder, and when putting it elsewhere, it should just readjust the internal editor path and throw a warning asking to adjust the path in the source script. Atleast it should work, didn't test it in a while, maybe something did break it...
     
  31. TiagoMartins

    TiagoMartins

    Joined:
    Mar 15, 2015
    Posts:
    12
    Ok, I managed to understand the problem that I had previously

    I can load node types from external libraries, dynamically, BUT, the editor project needs to have it referenced, so basically I created a project to have the editor specific classes and the node specific classes, this way everything gets serialized properly

    I guess we learn something new every day
     
  32. ScriptGeek

    ScriptGeek

    Joined:
    Mar 4, 2011
    Posts:
    45
    I'm curious about node transitions, how do they work?
     
  33. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Currently, they're very simple and unflexible, as they are in a WIP state. They will get a rebuilt when the basic mechanisms are ready:)
    I think you want to know how the transitoning process works, so you could take a look at NodeEditor / Caculation goup (in the develop branch of couse). There you'll find 1. the transitioning system and 2. the calculation system.

    Basically, the transitioning system has a list of canvases that are currently trasitioned. The canvases themselves store the current Node and Transition.
    Each frame will be updated with UpdateTransitions: If there's no current transition in the canvas, it will look for a new transition on the current node that has all conditions met (they don't work currently, see the serialization problem of funcs and the WIP UnityFunc). If the node doesn't have transitions, it will stop the transitioning process in this canvas.
    Then, it will be checked if the current transition is finished (handled by the transition, for now just a simple timer) and, if true, will switch to the node the transition points to.
    When drawing each node and transition check if they are the current ones, and draw apropriately. The transition also checks for the progress of transitioning.

    That process won't change much as the unflexible stuff is in the transitions themselves. I hope you understood what I meant;)
     
  34. GamesDeveloper12

    GamesDeveloper12

    Joined:
    Nov 7, 2013
    Posts:
    18
    Hi,

    How could i get a reference to the nodes that a node is connected to ?

    Currently i have a function in the NodeEditorWindow.cs script which loops through all of the nodes and as i loop through i would like to check which nodes the current node is connected to. I have added a variable called "connectedNode" to my "chemicalNode" which only has one output and have used the "TransitionConnected" event to try and store the connected node in the variable but when i try to use it in the editorloop i get a null pointer error.

    void TransitionConnected(NodeInput t)
    {
    Debug.Log("chemical "+this.chemicalName+ " has been connected to equipment node");
    Debug.Log(t.body.name); //correct name printed
    this.connectedOutputnode = t.body;
    }

    foreach(Node n in mainNodeCanvas.nodes)
    {
    if (n.GetType().ToString() == "ChemicalNode")
    {
    ChemicalNode cm = (ChemicalNode)n;
    Debug.Log(cm.connectedOutputnode.name);
     
  35. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Ok before I test, four notes:
    First, the event is called OnAddConnection but I assume you did type the right name in the actual code when it prints the correct name.

    Secondly, this callback is called on EACH node, not just the node this input belongs to. I might change this later on as it will likely rise confusion... For now, it'll work this way (pseudocode):
    Code (csharp):
    1. if (t.body == this) // We are the actual owner of the NodeInput
    2.     t.connection.body.connectedOutputNode = this;
    3. // OR
    4. if (t.connection.body == this) // We are the actual owner of the NodeOutput of the new connection
    5.     this.connectedOutputNode = t.body;
    Third, you actually don't need the event when you can just access the connection body like this:
    Code (csharp):
    1. if (node.Inputs[0].connection != null) // Be sure you do have an input!
    2.     connectedOutputNode = node.Inputs[0].connection.body;
    Last, there is a problem in the save system which limitates your possibilities regarding referencing scriptableObjects in Nodes and NodeKnobs. When you save the node like this the variable will still point to the scriptableObject in memory, not the one in the save file, so on reload it will be null. I've attempted to overcome this by implementing the GetScriptableObjects and CopyScriptableObjects in both Node and NodeKnobs which is basically an integration into the save system and help you remain the correct references to the scriptableObjects.
    Currently they do not work completely though, I've just spotted an error that these additional scriptableObjects are not always accounted for. But if you do like in my third point this shouldn't matter for you.
     
    Last edited: Feb 27, 2016
  36. GamesDeveloper12

    GamesDeveloper12

    Joined:
    Nov 7, 2013
    Posts:
    18
    Thanks, i got rid of the event and just used:

    Code (CSharp):
    1. if (node.Inputs[0].connection != null) // Be sure you do have an input!
    2.     connectedOutputNode = node.Inputs[0].connection.body;
    and it works perfectly for what i need.

    Thanks again
     
  37. ScriptGeek

    ScriptGeek

    Joined:
    Mar 4, 2011
    Posts:
    45
    Thanks for the info, Seneral. It does sound a bit confusing, but I think I understand where my project needs to go for now. It sounds like the NodeEditor wields the sole power of handling transitions and my project is working with collections of Node objects as a data model, so I'll just develop a way to centrally manage traversing the Node graphs from both the Editor and at run time.
     
  38. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Can you tell me your use case so I can take a look how I can fit it in the transition model I'm planning? I'd really like to make it very generic but I simply don't know what people will possibly use it for;)
     
  39. ScriptGeek

    ScriptGeek

    Joined:
    Mar 4, 2011
    Posts:
    45
    Sure, I'll try to explain it clearly. I'm using the Simple Node Editor as a visual node editor for a data model made up of node graphs by linking nodes together via the splined connections, which is already provided by the Simple Node Editor. Think of a node graph as a tree for now, but it will eventually need to act more loosely as an undirected graph (like a state machine, similar to PlayMaker in the Unity Asset Store), while allowing the possibility for multiple branches in the same graph to be traversed simultaneously. It needs to be able to traverse through the nodes both at editor and run times (editor for testing and run time while using the graph's logic in-game). The decision making of the node graph traversal will be made by logic acting on a set of various rules that are assigned to each node. The rules determine the direction of traversal from one node to the next, so the flow of transitions can happen both forwards and backwards. The flow will always begin at a root node and continue down through its descendants as the logic in the node graph dictates, but also have the option to travel backwards like following a trail of breadcrumbs that were dropped so the logic knows where to go when reversing directions. This is about as generic as I can explain it without giving away the top secret project I'm working on, so I hope this helps. If you need more specifics, I'll be glad to explain in PM.

    EDIT: Actually, I didn't realize the state machine behavior was mentioned earlier in this thread. I need to keep up on this better. It sounds like I need to either wait for this functionality, help out with adding this to the framework, or implement my own proprietary solution for use with my project.
     
    Last edited: Feb 28, 2016
  40. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Still thanks for posting this, I actually have to improve the existing transitioning system to fit your use case - you can currently only traverse one path in a nodecanvas at a time;)
    If you want, I can try to 'extract' the WIP statemachine system to a seperate feature branch (still merged in develop) so you can create a diff and possibly get started improving it yourself if you want;) I'd gladly help you get started there, because I'm currently just developing a solution for the conditional statement of transitions:)
     
  41. iddqd

    iddqd

    Joined:
    Apr 14, 2012
    Posts:
    403
    Hi Serenal

    The ObjectField is currently not working, correct?
    I keep getting an ExitGUIException whenever i open up the selection window.

    Thanks
     
  42. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    This is right, there is a very old bug on Unity's side that causes each picker field (object, color, etc.) to throw that error when inside a try catch block (The Node Editor does wrap one around the drawing function). A workaround I made was to only catch UnityExceptions (not all Exceptions) which mysteriously fixed it, but there was a period where I forgot that and changed it back to Exception before noticing, so depending on which commit you're using you'll experience this, sadly :(
     
  43. iddqd

    iddqd

    Joined:
    Apr 14, 2012
    Posts:
    403
    yeah i saw your post on unity answers and tried that UnityExceptions fix, unfortunately it didn't work for me.
     
  44. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    Oh, thats really unfortunate. I thought it atleast had a workaround. So Node Editor does throw these errors when you open such a field? I really hope Unity will finally fix this, it is annoying as hell:( You have not many options here, the try catch block is vital to not crash clumsily when an error occurs...
    But I plan a runtime version of this, as every other control, too, so maybe that'll be a solution.
     
  45. iddqd

    iddqd

    Joined:
    Apr 14, 2012
    Posts:
    403
    Sorry that was my mistake :rolleyes:. I put the try catch around "return UnityEditor.EditorGUILayout.ObjectField(GUIContent.none, obj, typeof(T), allowSceneObjects) as T;"

    Now i changed it in the NodeEditorWindow.cs to UnityException and it worked.

    Really love this NodeEditor!
     
  46. GamesDeveloper12

    GamesDeveloper12

    Joined:
    Nov 7, 2013
    Posts:
    18
    how do i change the knob colour ?
     
  47. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    You currently only have the option to create a new Knob type or change the existing one, but due to an issue on github I plan to add support for changing knob color, also by providing trigger conditions (like if the value is this, then that color, etc.)
     
  48. GamesDeveloper12

    GamesDeveloper12

    Joined:
    Nov 7, 2013
    Posts:
    18
    Thanks, where is the knob type so i can change the colour or add a new one ?

    EDIT:

    I found it, after a little tinkering i didn't realize the colour set in the itype declarations was the knob colour, i thought it was the line colour
     
    Last edited: Feb 29, 2016
  49. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,186
    You can find the default float knob type in ConnectionTypes.cs, at the very bottom. You can also always create a new one for different types and the WIP Action and UnityFunc feature branch on the repo also has support for arbitrary connection types without having to create a connectionType for them explicitly:)
     
  50. ScriptGeek

    ScriptGeek

    Joined:
    Mar 4, 2011
    Posts:
    45
    Go ahead and split the WIP state machine into a separate branch and I'll work on it.