Search Unity

Simple node editor

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

  1. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    I still can only assume what the error cause is...

    But I can recommend you to do it this way, which uses the correct functions and is also the most generic, because you don't need to modify the code when you add more nodes:
    (It assumes the Data contains node ID (type) and position + node specific data)
    Code (csharp):
    1. CanvasType nodeCanvas = NodeCanvas.CreateCanvas<CanvasType>();
    2. NodeEditor.BeginEditingCanvas(nodeCanvas);
    3. foreach (NodeData data in nodeDatas)
    4. {
    5.     Node node = Node.Create (data.nodeID, data.position); // Create node of the correct type at the position
    6.     node.LoadCustomData (data.data); // Load custom data
    7. }
    8. NodeEditor.EndEditingCanvas();
    For that to work, you need to add these two functions in Node.cs or your custom base node class and overwrite these functions in each node to return custom data and read it back in:
    Code (csharp):
    1. // Node base class
    2. public virtual void LoadCustomData (params object[] data) {}
    3. public virtual object[] SaveCustomData () { return new object[0]; }
    4.  
    5. // In each of your nodes
    6. public override void LoadCustomData (params object[] data)
    7. { // Read in all saved variables
    8.     someIntVariable = int.Parse(data[0]);
    9. }
    10. public override object[] SaveCustomData ()
    11. { // Return all variables that should be saved
    12.     return new object[] { someIntVariable };
    13. }
    Then of course, to save the NodeData from a canvas:
    Code (csharp):
    1. List<NodeData> nodeDatas = new List<NodeData> ();
    2. foreach (Node node in nodeCanvas.nodes)
    3. { // Save node data
    4.     NodeData data = new NodeData ();
    5.     data.nodeID = node.GetID (); // Save node type
    6.     data.position = node.rect.position; // Save node position
    7.     data.data = node.SaveCustomData (); // Save custom node data
    8.     nodeDatas.Add (data);
    9. }
    Additionally to that you of course have to handle the connections, which should be possible to handle. For example, give each node a real unique ID (not the node ID which just represents it's type) and then in the NodeData save the off-going (output) connections of each node, including source knob index, target node ID and target knob index.´
    Then restore them, after all nodes are restored, with this:
    Code (csharp):
    1. FindNode(targetNodeID).Inputs[targetKnobIndex].TryApplyConnection (FindNode(sourceNodeID).Outputs[sourceKnobIndex]);
    That makes it nearly as easy as a normal automatic serializer, all you have to do is override the two node function to make a new node type save custom data to a custom, unknown format. With that you could, with workarounds, easily do a proper XML save format (at least theoretically).

    All that is only pseudo code, but hope it works for you:)
    Seneral
     
    Last edited: May 31, 2017
  2. Jamsa78

    Jamsa78

    Joined:
    Mar 29, 2017
    Posts:
    96
    ....um, yeah.... Ok,.I see my childish attempt was...childish. :D

    I'll look into it tomorrow, thanks! :)
     
  3. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Haha, don't worry, you just tried to do everything manually when there are specific functions provided by the framework that do the job correctly:) If one thing is missing - errors are likely to appear! But you can't expect anyone to know the framework's guts the first time they're using it;)

    Actually, writing this, it would make sense to include that into the documentation. It's a common issue I would assume, many have tried already but I hadn't yet have the time to include it into the framework fully fleshed-out nor write it properly down and into the documentation. But that seems like a good start to me;)
     
    Jamsa78 likes this.
  4. Jamsa78

    Jamsa78

    Joined:
    Mar 29, 2017
    Posts:
    96
    Haha, thanks. I know. :) But it's still fun to pretend that I know everything...yeah, I'm wierd like that! :D
     
  5. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    That's not weird, but normal as a beginner;)
     
  6. Jamsa78

    Jamsa78

    Joined:
    Mar 29, 2017
    Posts:
    96
    But...but..but...I wanna be WEIRD!!! :(:eek::confused:o_O:D
     
  7. Jamsa78

    Jamsa78

    Joined:
    Mar 29, 2017
    Posts:
    96

    Ok, now that I'm working again... ;)
    The line:
    CanvasType nodeCanvas = NodeCanvas.CreateCanvas<CanvasType>();
    Doesn't work, CanvasType is unknown, changing it to NodeCanvas makes it say CreateCanvas is unknown...same goes for NodeEditor.BeginEditingCanvas(nodeCanvas);

    Did you take this from your fancy smancy dev branch by any chance? :D

    This code is placed in SaveManager btw...right/wrong?
     
  8. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    No, it's actually only pseudo code off my head:)
    But indeed, it's based off the develop branch... sorry about that. Although you would probably be better off just using the develop branch if you've not modified the base framework too much - it's better, more flexible and, as you noticed, easier for me to give support for;)

    If you do take the develop branch, the first error still remains. Basically CanvasType was intended to be replaced by your custom canvas type (if you have one) or the default Calculation canvas (NodeEditorFramework.Standard.CalculationCanvasType). Passing in NodeCanvas also throws an error because that is (in the develop branch) only the base class for other dedicated canvas types and not a proper canvas type anymore.

    The placing doesn't really matter much tbh. I do not recommend changing framework source if that's not really necessary, in this case I'd make a seperate class dedicated to your canvas/database exchange (import/export).
     
  9. Jamsa78

    Jamsa78

    Joined:
    Mar 29, 2017
    Posts:
    96
    Haha, naughty boy. :D Giving me fake code! :D

    Yeah, I know you like the new fancy smancy dev branch (FSDB) ... A LOT!!! :D But as you say "do not recommend changing framework source if that's not really necessary". I feel the same. ;) So I'm sticking with the one I got.

    Yeah, I didn't think that placing would matter (because it shouldn't! ;) ), so it's nice to know that something is right!! :D Or a least not totally wrong. :p

    Soo...knowing that I'm not using FSDB, what do I do from here, regarding getting the canvas to work? :)
     
  10. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Alright... can you PM me a small version of your project so I can reproduce the error? Just the framework+import/export code of yours and all other related things if necessary. Thanks!
     
  11. Jamsa78

    Jamsa78

    Joined:
    Mar 29, 2017
    Posts:
    96
    Sweet. :) :) :)

    Yes, I'll get it ready for you first thing tomorrow! :) Thanks a bunch!!;)
     
  12. Jamsa78

    Jamsa78

    Joined:
    Mar 29, 2017
    Posts:
    96
    PM sent. :)
     
    Last edited: Jun 1, 2017
  13. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    Hello. I have been looking at integrating this into our project. It looks promising, but I have noticed a few issues.

    Firstly, just using the default RTNoteEditor, if I change root rect X or Y to be greater than 20, the right click popup stops working. If its less than 20, the popup is offset by that ammount (e.g. if root rect x is 15, the popup is 15 pixels off).

    I was able to fix it by removing some calls to GUIScaleUtility.GUIToScreenSpace in OverlayGUI, so

    Code (CSharp):
    1.         public void ShowAsContext ()
    2.         {
    3.             popup.Show (GUIScaleUtility.GUIToScreenSpace (Event.current.mousePosition));
    4.         }
    5.  
    6.         public void Show (Vector2 pos, float MinWidth = 40)
    7.         {
    8.             popup.Show (GUIScaleUtility.GUIToScreenSpace (pos), MinWidth);
    9.         }
    becomes

    Code (CSharp):
    1.         public void ShowAsContext ()
    2.         {
    3.             popup.Show (Event.current.mousePosition);
    4.         }
    5.  
    6.         public void Show (Vector2 pos, float MinWidth = 40)
    7.         {
    8.             popup.Show (pos, MinWidth);
    9.         }
    Given I have only been playing with this for a few hours now, I am not sure if this fix would break anything else, but it seemed to work fine for me.

    The next issue I noticed is with the calc node, when selecting the type, the list is not in the same format as the right click popup, and is offset (even at a zoom of 1). It looks like this is a known issue though.
     
  14. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Hey,
    yep, the popup issue is known, because the standard popup controls do not support GUI.scale for some reason:( The context menu you see has been replaced by a custom one, but most popup controls are still missing...
    And regarding the context offset, you're right, thanks:) Will have to look further into it if that does not break anything, but it should be alright.
    Seneral
     
  15. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    I have written some custom save and loading code to work with our own in-house data system. It seems to be working very well, but I am stuck at creating nodes from code on loading.

    I am creating nodes like this:

    Code (CSharp):
    1. Node createdNode = Node.Create(nodeType, position);
    It seems that NodeEditor.curNodeCanvas is null when this is called (causing an exception within Node.cs).

    I tried placing it within the Update loop as such:

    Code (CSharp):
    1.                 if (NodeEditor.curNodeCanvas != null)
    2.                 {
    3.                     LoadNodeCanvas(); // creates all the nodes using Node.Create
    4.                 }
    This does nothing, but when I add a node by hand in game (right click and selecting a node), NodeEditor.curNodeCanvas suddenly becomes assigned to and the nodes are then loaded correctly.

    How do I go about creating nodes from code reliably? I saw functions such as "NodeEditor.BeginEditingCanvas" being mentioned earlier, but I can't find any reference to them in any of the scripts. I feel like I must have missed something...
     
  16. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Hey sorry for the late reply.
    I'll have to come back to you, I'm currently in the final phase for my essay, finishing friday:)
    Seneral
     
  17. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    I managed to get it to create a new canvas and add to it correctly by adding this to my LoadNodeCanvas() function:

    Code (CSharp):
    1.                 cache.NewNodeCanvas();
    2.                 NodeEditor.curNodeCanvas = cache.nodeCanvas;
    This appears to be working, though I am not entirely sure if its going to break anything.
     
  18. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Don't know for the master branch right now for sure right now, sorry.
    I'm preparing a big update for the develop branch that finally add some long desired features, including a proper import/export system with custom formats and even the possibility for formats to specify own GUI to access custom databases. Also I'm considering implementing the long-discussed new knobs system. Finally, I remade the process of creating nodes which makes most stuff previously found in the Create function properties, which also eliminates an old design-flaw of the node types fetching system.
    Might take a little longer though, I expanded my goals while implementing the import/export system...
    Seneral
     
  19. tobia88

    tobia88

    Joined:
    Aug 1, 2013
    Posts:
    5
    Hey, i still meet Type mismatch issue while i'm trying to save node in my custom canvas by overriding OnBeforeSavingCanvas() , i found the same issue eventhough from the DialogueExample, how do i solve that?
     
  20. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    What do you want to accomplish? You're overwriting the NodeCanvas.OnBeforeSavingCanvas, you don't need that to save your nodes. This is done automatically...
    Seneral
     
  21. robocup30

    robocup30

    Joined:
    May 2, 2017
    Posts:
    7
    Hi,
    I'm not sure if this is the correct place to ask this since my question involves inspector but does anyone know how to hook up the node with inspector? More specifically, I want to be able to attach scripts to my nodes and be able to edit them on inspector like you can attach behaviour to animator state as seen here.

    Unfortunately, the best I could do was this.


    Instead of State variable just being a field in inspector where I can drag and drop an instance of it, I want to be able to attach the script directly to the state similar to how you attach behaviour to animator states and be able to access script's variables and modify them through inspector.

    My node is a ScriptableObject that looks something like this
    Code (CSharp):
    1. public class Node : ScriptableObject
    2. {
    3.     public int nodeID;
    4.     [HideInInspector] public Rect rect;
    5.     public string title = "";
    6.     public State state;
    7. }
    And I'm planning on State to be a script to control enemy AI in my game.
    Thank you!
     
  22. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    You can't do that since ScriptableObjects are scripts themselves and the component-based script system of unity only works on GameObjects.
    Not sure if you use this framework or an own implementation but usually the nodes itself are intended to provide the functionality. So instead of using generic scripts, extend Node and implement the functionality there.
    Luckily you can create a custom inspector for the scriptable objects so if you do want to have a proper GUI in the Inspector when selecting a node, you can do so.

    Interesting idea to put scripts on nodes, though. But on the technical side it would be a mess since your graph would then be an object tree rather than editor script objects and thus be bound to the scene.
    Also, handling integral stuff like connections are then more difficult to implement generically. Basically any script could then 'request' connections as these are what define a node and there can be any number of it.
    Really, I don't think the component structure would work very well for a generic, simple node editor (atleast in most cases, for the node graph of TC2 it did work very well).

    Seneral
     
    robocup30 likes this.
  23. robocup30

    robocup30

    Joined:
    May 2, 2017
    Posts:
    7
    Ok, thanks for super quick reply! I guess I'll try and move all the functionalities I had planned for State object up to Node object then.
     
    Seneral likes this.
  24. jilt

    jilt

    Joined:
    Nov 7, 2014
    Posts:
    49
    Is it possible to change the values of nodes from a regular monobehaviour, outside of the patch?
    I've tried the following inside RTCanvasCalculator but I'm still seeing the calculation with the data in the patch rather than my randomized values

    Code (CSharp):
    1. public void Update()
    2.         {
    3.             if (Input.GetKeyDown (KeyCode.Space)) {
    4.  
    5.                 List<Node> nodes = getInputNodes ();
    6.                 foreach (Node node in nodes) {
    7.                     Debug.Log ("Node: " + node.name);
    8.                     node.Outputs [0].SetValue<float> (Random.value);
    9.                    
    10.                     node.Outputs [0].SetDirty ();
    11.                    
    12.                     List<NodeInput> inputs = node.Inputs;
    13.                     foreach (NodeInput input in inputs) {
    14.                         Debug.Log ("Input: " + input.ToString ());
    15.  
    16.                     }
    17.  
    18.                     List<NodeOutput> outputs = node.Outputs;
    19.                     foreach (NodeOutput output in outputs) {
    20.                         Debug.Log ("Output: " + output.ToString ());
    21.                         Debug.Log ("Value: " + output.GetValue<float> ());
    22.  
    23.  
    24.                     }
    25.                 }
    26.                 canvas.Validate (true);
    27.                 canvas.TraverseAll ();
    28.                 CalculateCanvas ();
    29.             }
    30.         }
     
  25. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Well yes it is possible, but first let's see what that code above does.
    You're getting your input nodes by getting all nodes not connected. This may return nodes of ANY type, if a calculation node is in the graph which has no connected inputs, it will be in that list. That may cause problems because you rely on the fact that is has one input of type float at the first position. Then you're setting it's output knob value manually.
    After debugging you tell the canvas to be recalculated. This will start with all input nodes (the ones your iterate over, not nodes if type input) and propagate down the graph. But the input nodes are all calculated and they assign their knobs to the value they want, which in this case overwrites the random values you have set previously.

    So instead of setting the knob value directly, get all nodes of a specific type in the graph, like canvas.nodes.OfType<InputNode>(), and then assign a property in it that it should be assigned to it's output, in case of the InputNode it would be node.value. This will 1. assure you only assign to nodes that are really supposed to be inputs and 2. assign the correct value as desired by the node.

    Finally, a few notes on your last bit of code. You call Validate on the canvas which is a good thing, but you only need it whenever the canvas itself changes, so most probably only after loading or OnEnable. Also, no need to call TraverseAll as CalculateCanvas does the same and outputs the log. So you only want to call CalculateCanvas, else the canvas calculation is performed twice.

    Hope that helps you:)
    Seneral
     
  26. jilt

    jilt

    Joined:
    Nov 7, 2014
    Posts:
    49
    Thanks Seneral!
    canvas.nodes.OfType<InputNode>() did the trick.

    the last bits were just me trying random things to get the data updated with my random values.
     
  27. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Hello everyone,
    today I finished what is one of the biggest, if not the biggest, update in a long time:)
    Alot has happened and I'm very excited about this update as it adresses two of the most requested features, a new, more flexible connection system aswell as custom Import/Export formats:) Additionally I reworked some UI and updated the RTNodeEditor GUI.
    I split everything in 4 commits, which took quite a while to merge correctly because I developed everything together...

    1. dc85da4 #74 Property-based Node and new ConnectionPort system

    - Node is now defined through properties rather than with the Create function (see nodes), fixing #72
    - Create has been replaced by the optional Init function
    - New ConnectionPort/ConnectionKnob/ValueConnectionKnob level-hierarchy for node connection ports:
    - ConnectionPort: Basic connection between nodes, straight line
    - ConnectionKnob: A Knob on the node that can connect to other knobs on other nodes through connections
    - ValueConnectionKnob: A Value-Knob defined by a type and designed to pass values to it's connections
    - ConnectionPorts are now defined through Attributes right on variables in the Node definitions (see nodes)
    - ConnectionPorts of all levels have preset-styling similar to ConnectionTypes previously, each with different settings
    - Inputs/Outputs are now weakly-typed, maximum connection counts are seperately specified
    - Currently not possible to edit Multi-Multi connection knobs due to interfacing, but structurally it's finally possible

    NOTE: This commit replaces the old Knob system and is NOT COMPATIBLE, all save files done so far LOOSE CONNECTIONS and NODE LOOSE POSITION! This is sadly not recoverable without messy duplicate code due to the way the unity serialization system works. So you need to reposition all your nodes and reconnect all your knobs. Sorry about that.

    2. 748d990 #43 New Import/Export system with XML IO format

    - Implemented modular IO system for custom formats
    - Added XML IO format using that system (theoretically working at runtime to save canvas between sessions)
    - Specify custom format location through Selector or GUI
    - Allows for custom database access and similar for import/export
    - Option between extending ImportExportFormat or StructuredImportExportFormat when implementing custom formats
    - Structured adds a layer of abstraction on the Canvas Data easier for file-based formats
    - Handles IDs, Serialized Fields, Creation and Access of the complex NodeCanvas structure

    3. 860f64d Small fixes, cleanup and comments

    - Small fixes to caching and saving
    - Small cleanup in save manager
    - Removed unnecessary event blocks (trying to fix #127)
    - Added and improved method summaries

    4. b3cd836 UI Rework: Synced runtime GUI with editor

    - Outsourced Interface to NodeEditorInterface, removing the deprecated SideWindow, leaving a clean Toolbar interface
    - Both RTNodeEditor and NodeEditorWindow greatly cleaned and simplified by using unified NodeEditorInterface
    - Added toolbar styles for runtime use, keeping the editor style in the editor window
    - Reworked switching between editor/runtime GenericMenu's by using wrappers around the editor one
    - Allows for differenciation between editor window, editor playmode and standalone popups
    - Improved node colouring to use GUI.color instead of custom textures
    - Fixed small glitches and styling issues
    - Added keyboard shortcut to delete nodes ('Del')


    Finally, I updated the Web GL Demo to reflect the latest changes, although the XML import/export won't work obviously because of WebGL.
    I know it's alot to read through but before updating I strongly recommend you to read it.
    Hope it works for all of you, might need some final testing:)
    Seneral
     
    Last edited: Jul 2, 2017
    Jamsa78 likes this.
  28. adsilcott

    adsilcott

    Joined:
    Aug 30, 2014
    Posts:
    55
    Hi, thanks for this. It's a great project and I appreciate that it's opensource and free.

    I was using the original code from the first page for a while, and I liked it. It's all editor code, as it should be, because this is all stuff you only need in the editor. I was able to use any EditorGuiLayout methods that I wanted. I'm disappointed that the new system isn't like this. For example:

    Code (CSharp):
    1.  
    2. GUILayout.BeginHorizontal ();
    3.  
    4. line.speaker = RTEditorGUI.ObjectField<CharacterDefinition> (new GUIContent(""), line.speaker, false, GUILayout.Width(speakerWidth));
    5. //line.speaker = (CharacterDefinition)EditorGUILayout.ObjectField (line.speaker, typeof(CharacterDefinition), false, GUILayout.Width(speakerWidth));
    6.  
    7. line.line = GUILayout.TextField (line.line);
    8.  
    9. GUILayout.EndHorizontal ();
    10.  
    I commented out the line I used to use which worked fine. The new one doesn't work-- it doesn't limit the width of the object field.

    It also just bothers me that I'm writing editor code that isn't in an editor folder. I assume this is to have more control over how the nodes are rendered? Are there other reasons for doing it this way?
     
  29. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    No worries, you can use the editor GUI without problems;)
    But reason that the whole framework is based upon runtime GUI (even using RTEditorGUI) is that you can actually use it at runtime (see the WebGL demo). But noone forces you to keep that compatibility.
    One option is to move the whole framework in an editor folder, f E. Plugins/NodeEditor into Plugins/Editor/NodeEditor.
    Or you can just move your nodes in the editor folder so they are excluded from runtime if you happen to build (but the framework will be included). And finally, if you want to keep certain compability or need to use the nodes at runtime (not necessarily graphically) just wrap the Editor GUI code in #if UNITY_EDITOR

    Hope that clears that up:)
    Seneral
     
  30. paintbox1

    paintbox1

    Joined:
    Jan 20, 2014
    Posts:
    36
    Hi I dont know where to post this stuff in github because I've got several questions and dont know the related issues. So heres my Feedback so far :)

    1. The type fetching of the nodes expects a field called ID in every node type. Thats weird. It should take a property like GetID or something that throws Errors in the Compiler, if the node type doesnt implement it.

    2. The Editor always creates an empty object for some saving purpose in the current Scene. Even if not necessary.

    3. I see we have gone rid of that sidebar and have a menu instead(which I consider much cleaner). But where can I draw my canvas related UI stuff now? My whole canvas represents a sequence of cutscenes and I want to edit the used actors at the scope of the canvas. Same goes for my node related stuff. I have detail UIs in Nodes which just dont fit in the Node Body.

    4. With the new Knob System, how would I properly add new ConnectionKnobs dynamically. I need them to add Player choices in the editor.

    5. When using the new Multi Connection Feature, is there already a way of deleting Connections on Multi to Multi knobs?

    Greetings
     
  31. adsilcott

    adsilcott

    Joined:
    Aug 30, 2014
    Posts:
    55
    Ah Thank you! I thought I tried that earlier but I must have been doing something wrong... I'll try what you suggested!
     
  32. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Hey, good points:)
    1. That's unfortunately needed, didn't think that it isn't mandatory...
    To acess GetID you need an instance, but because of several problems I abandoned the approach to create a default node instance on initialization for obvious reasons (I did that in the previous version) so I fell back on the const ID field and forgot it isn't strictly mandatory.
    But first off, come think about it, implementing ID makes sense. Calling MyCustomNodeType.ID instead of having an instance to call GetID is way more comfortable. But I can't enforce the ID field through the compiler because it is const and constants can't be abstract/overridden...
    You see my problem? I could fall back to creating a instance to access GetID and then delete it incase const ID is not found but that's not very clean either...

    2. Yep, will adress that:)

    3. You would need to add the sidebar yourself, if you can't adjust the UI to fit the Toolbar system. Sorry about that, it is easy to implement though... Or you could use the modular panel only appearing when selecting a node.
    Do you think I should add the basic side panel implementation back into the interface for custom use? You'd then fill it with own custom code...

    4. I'm still working on that. Actually, we now have two ways to make them dynamic!
    First, a seperate list and script interface to create knobs (or generally speaking, ports) dynamically just as before.
    Second, declaring a List of ConnectionKnobs like normal knobs now and have it automatically adapt to some other list or custom condition to automatically provide knobs;)
    No restraints as to that compared to the old system, it simply is an added abstraction layer for most normal nodes. Still need to implement the interface to create the knobs dynamically though, but no big deal...

    5. No, not yet. We have a concept on the issue that is very promising but I didn't have the time to implement it yet. But most importantly Multi-Multi connections are no theoretically possible and also inputs taking more connections (given the outputs take only one).
    The editing is only the final step, but would appreciate help with that as it's currently not of high focus for me (still have lot's of other stuff to do besides the framework that I have to catch up to after this week on the framework).

    Thanks for the feedback!
    Seneral
     
  33. paintbox1

    paintbox1

    Joined:
    Jan 20, 2014
    Posts:
    36
    1. If you really want to use the ID like that, it isnt an instance property at all but rather additional type info? Because then you could just make it a mandatory Parameter to the Node Attribute.

    3. Personally I think it was a good thing to get rid of the sidebar, because unity already has one. Best Scenario I can imagine would be to use the selected object to Display its inspector Code in the unity inspector. This already works for nodes, but when clicking into empty canvas space the inspector still shows the last selected node instead of the canvas.
    If you would set the canvas as selected object, we could simply use the unity inspector to display stuff like that by creating custom editors for your canvas and node types. You could simplify it even further by creating a custom Editor for the node and canvas base classes and specify in the customeditor Attribute that it shall be used for derived classes too. Like this:
    Code (csharp):
    1. [CustomEditor(typeof(NodeEditorFramework.Node), true, isFallback = true)]
    2. public class NodeInspector : Editor
    3. {
    4.     public override void OnInspectorGUI()
    5.     {
    6.         (this.target as NodeEditorFramework.Node).DrawInspectorGUI();
    7.     }
    8. }
    the creator of a new node type just needs to override the virtual DrawInspectorGUI method of the base class in the derived node class. Same can be done for Canvas once it gets selected properly.

    4. I really like to have those both Options. Personally I would prefer the list with Attribute. But it would require using something like an observable Collection to know when someone added something to it. ObservableCollection was introduced in 3.0 but I think something like that would be sufficient: http://answers.unity3d.com/questions/677956/getting-notified-when-modifying-a-collection-ala-c.html

    5. Its not important to me. Was just curious if youve already implented it :)
     
    Last edited: Jul 4, 2017
    Seneral likes this.
  34. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    1. Good idea actually, although not perfect either as up until now the NodeAttribute was optional and inly included additional information about the integration in the framework, so to speak. Will have to think about that... Currebtly I took the sample node approach again, although not as bad as before.
    If you do specify a static ID and have an attribute specifying the node path that will do, too, without creating that sample node.

    3. Brilliant idea:) Played with something similar before but hadn't thought about that in this context... Quick to implenent too, based of somehing already there:)

    4. I thought more about a method to set the count of a given knob collection manually...
    Observable collection seems easy in some cases but limiting in others...

    Seneral
     
  35. paintbox1

    paintbox1

    Joined:
    Jan 20, 2014
    Posts:
    36
    1. your "sample node" Approach aint as dirty as you think. it is common practice in other Frameworks. especially in IOC Containers. I wouldnt worry too much about that.
    2. I totally understand your concerns with observablecollections, though i would prefer a method which detects and applies changes. Setting the count is a bit inconvenient if i just want to delete an item in the middle of my Collection. would be way easier to just remove it from my collection and then call a function like refreshlist()

    greetings
     
  36. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    1. Cool, always learning something new:)

    2. I'll have to take a look at that:) For now I'll probably implement a basic interface for managing knobs as before, and will extend on that later on to make it easier for collections:)

    Thanks very much for your input though, much appreciated!
    Seneral
     
  37. paintbox1

    paintbox1

    Joined:
    Jan 20, 2014
    Posts:
    36
    im always glad to help you making your framework more like I want it to be xD
    Sorry, Im no help with directly implementing stuff in the repo but for several reasons I cant.
    Greetings
     
  38. adsilcott

    adsilcott

    Joined:
    Aug 30, 2014
    Posts:
    55
    I'm doing something like this:
    Code (CSharp):
    1. public override Node Create (Vector2 pos)
    2. {
    3.     DialogueLineNode node = CreateInstance<DialogueLineNode> ();
    4.     node.CreateOutput ("Next Node", "NodeNext");
    5.     return node;
    6. }
    If I replace node.CreateOutput() with just CreateOutput(), then the knobs don't get added. Likewise if I call CreateOutput() anywhere else in code they don't get added. What am I doing wrong?
     
  39. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    The Create function as it is in older versions (recently revamped that completely for good) is responsible for creating new nodes, obviously, but relies on an internal sample node to call Create upon.
    What you try to do is create knobs on the sample node (calling this.CreateOutput, not node.CreateOutput). The new system is far ahead in that regard:) If you're new try out the develop branch, it'll probably serve you better as it's easier to work with imo.
    Seneral
     
  40. adsilcott

    adsilcott

    Joined:
    Aug 30, 2014
    Posts:
    55
    OK I switched to the develop branch. I'm really not clear on how to add knobs now. Can you give an example? All of the examples use the old system. I tried instantiating a ConnectionKnob and initializing it, adding it to the list, etc. Sorry if I'm missing the instructions somewhere, I'm trying to read through the thread and the code...
     
  41. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Yep, there are no upgrade guidelines yet I'm afraid and keeping the docs up to date is currently too much for me:(
    But a good place to look at are always the nodes found on the Nodes/Example folder. Basically we switched to a property-based node model where everything is specified through properties rather than in the Create function. That also applies to knobs, they are now declared as variables and marked with attributes to specify information and that's it.
    Apart from that the whole connection system got a major overhaul to be more flexible, which also means different naming conventions and features... but it's for the best in the end.
    A good place to read further is our development issue for that feature or the release notes mentioned a few posts above:)
    Hope that helps. Tell me if you got problems upgrading:)
    Seneral
     
  42. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Implemented it, think it turned out really well:)
    See the commit here... Thanks again for that suggestion:)
    Seneral
     
  43. adsilcott

    adsilcott

    Joined:
    Aug 30, 2014
    Posts:
    55
    Thanks for the help. The attribute system looks cool. Unfortunately I need to be able to add connections dynamically, and from previous comments it sounds like maybe that's not implemented yet? So I guess I'll go back to the master branch and try to get that working again.
     
  44. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Hey, sorry about that. Seems more people than I thought use it. It should not take nuch longer to implement thouh...
     
  45. paintbox1

    paintbox1

    Joined:
    Jan 20, 2014
    Posts:
    36
    I dont see a DrawPropertyEditor call in the canvas editor. How can I draw my Canvas related UI stuff using this? Looks like the canvas just draws the nodes?
     
  46. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    Hm can implement that so far there was nothing like a canvas property editor, can change that though, just a simple virtual GUI method in NodeCanvas to override. Didn't think of that...
    Seneral
     
  47. adsilcott

    adsilcott

    Joined:
    Aug 30, 2014
    Posts:
    55
    It's difficult to edit text in a text area, because when you hit the arrow keys to move the cursor, the node moves instead. How do I change this behaviour?
     
    Last edited: Jul 5, 2017
  48. Seneral

    Seneral

    Joined:
    Jun 2, 2014
    Posts:
    1,206
    It has been fixed on the develop branch, check out this commit:) You can manually implement these changes if you want or switch completely, that's up to you:)
     
  49. paintbox1

    paintbox1

    Joined:
    Jan 20, 2014
    Posts:
    36
    I would really appreciate that. Like I said, I need to manage some things at canvas scope.
     
  50. adsilcott

    adsilcott

    Joined:
    Aug 30, 2014
    Posts:
    55
    Thanks! I wasn't sure if it was fixed on the development version or not, since I switched back. I'm looking forward to the dynamic connection creation so I can switch back to the new version.