GithubHelp home page GithubHelp logo

Comments (35)

Seneral avatar Seneral commented on June 21, 2024

You're right, the documentation is still lacking some more advanced topics than just extending it. I do try to improve it when I have time:)

Auto generated documentation from the code would also be nice, but we just decided to use mkdocs to generate the documentation (will go live soon) so it would be a pain to refactor it again to ReadTheDocs or similar. If anyone has suggestions regarding this, I'd appreciate them:)

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

mkdocs is the same as readthedocs, readthedocs is just a service provider with webhooks (iirc).

Is there somewhere a basic guide how to get started with accessing nodes / traversing them? If not, could you write something small down?

If any kind of documentation-service is up, I would like to contribute to it. I did simliar with my python bot projects and got some experience with the parsing and auto-doc part.

Edit: Also, wow, what a fast reply.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

We started discussing it in #46 and groud actually made it possible with mkdocs in his fork. It is currently documenting stuff that's only in the dev branch so it's not replacing the 'old' one, found here, yet.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

And if we can use readthedocs works with mkdocs, that'd be amazing:)
As long as we can still keep manually written articles, too.

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

Hey, I'm still working on interfacing with it - and some problems seem to be hard to solve.

To give you some feedback on that - which could be a seperate issue, probably:

I tried to write a random selection node. The best solution I may have found is adding a hidden first output which references the selection. Not really pretty, it would make more sense to let Calculate return what nodes it calculated or having an out / ref parameter.

Looking at certain nodes only works with something like this:

NodeCanvas x = NodeEditorFramework.NodeEditorSaveManager.LoadNodeCanvas("Assets/Plugins/Node_Editor/Resources/Saves/test_case.asset");
NodeEditor.RecalculateAll(x);

otherwise all nodes always return 0 on their inputs/outputs. I am not sure if this is intended.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

I don't quite understand what you mean:(
Maybe you can explain it in more detail, and what it has to do with the documentation (or not)?

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

Ref / Out

In my case, I would use the framework to write a dialogue system, with different branches.

Since dialogues could/should have random dialogues downwards, it would be useful to have a intermediate node to select a random path downwards. From here out on I would need to traverse downwards.

Let's say I have a dialogue root, which references 1 child dialogue which chooses a random dialogue node on runtime. I would now have a hard time getting the right child-dialogue to traverse downwards. It's probably about me not understanding some case, but this is how it looks right now:

Image

The only solution I currently can come up with is using the intermediate random node to store an object attribute "selection", writing it in the calculate, use the parent, check the connection (which then is the random node), execute calculate on the random and move on to the randomNode.outputs[randomNode.selection].

There are probably multiple other cases where having and out parameter would be useful as utility.

Recalculating Nodes

I have this piece of code sitting in the Update of a random monobehaviour of an enabled scene:

    NodeCanvas x = NodeEditorFramework.NodeEditorSaveManager.LoadNodeCanvas("Assets/Plugins/Node_Editor/Resources/Saves/test_case.asset");
    NodeEditor.RecalculateAll (x);
    Debug.Log ("I may have loaded.");
    foreach(Node n in x.nodes) {

        // n.Calculate ();
        string s = "> " + n.name;
        n.ClearCalculation ();
        foreach (NodeInput ni in n.Inputs) {
            if (ni.connection != null) {
                s += " | INPUT: " + ni.connection.GetValue<float> ();
            }
        }

        foreach (NodeOutput no in n.Outputs) {
            s += " | OUTPUT: " + no.GetValue<float> ();
        }

        Debug.Log (s);
    }

If you disable RecalculateAll all inputs/outputs return 0. Is this intended?

Thanks for all the help.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

Yes, it is intended as the calculated values are not serialized. I think that should be reasonable though, and your problem should be aproached differently...
EDIT: If you do it in update, each time the canvas would be reloaded and recalculated. If it's an option, I would cache it and the calculation state, then you would do both actions only in the start function:)

So, you really need the random child node in the parent node? Or do you 'just' want to take a random path down the tree at the random node 'junction'?
In the latter case, I'd implement a feature I remember was requested long ago which I didn't do yet (I forgot) but I could implement it in five minutes. It would enable you to 'block' the outputs of a node, so the only thing the random node would do is block all but the randomly selected output and then the calculation would only continue on that selected node. Would that help you?

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

That would improve it!

Another alternative would be some attribute on a dialoge node and do checks in its calculation. But I guess blocking would work then.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

Ok, I'll come back to you when I'm back home and I implemented it:)

Edit: Sry, wrong button...

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

Thank you very much for your kindness. After that I would fork that repo and add custom types, like Bool, Int, GameObject, etc..

Also what do you think of the brighter, slightly different knobs? I could merge-request them too, if you'd like to.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

Don't know, I like them, maybe a bit too bright (considering the lines). But the style of the node editor is rather unimportant right now as it is up to the developer to customize it for his asset;)

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

To come back to the OP, I'd really want to write some more articles if I had more time... So I cannot exactly say when I'll be able to provide them:/

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

@DarkMio I added output blocking in this commit: a05493e

An example for the random branch node, where a random branch get's chosen which will be caluclated further and the others get blocked:

using UnityEngine;
using System.Linq;
using System.Collections.Generic;
using NodeEditorFramework;
using NodeEditorFramework.Utilities;

namespace NodeEditorFramework.Standard
{
    [Node (false, "Example/Random Branch")]
    public class RandomBranchNode : Node 
    {
        public const string ID = "randomBranchNode";
        public override string GetID { get { return ID; } }

        public override Node Create (Vector2 pos) 
        {
            RandomBranchNode node = CreateInstance<RandomBranchNode> ();

            node.rect = new Rect (pos.x, pos.y, 100, 200);
            node.name = "RND Branch";

            node.CreateInput ("Src", "Float");

            node.CreateOutput ("Branch 1", "Float");
            node.CreateOutput ("Branch 2", "Float");
            node.CreateOutput ("Branch 3", "Float");
            node.CreateOutput ("Branch 4", "Float");
            node.CreateOutput ("Branch 5", "Float");
            node.CreateOutput ("Branch 6", "Float");
            node.CreateOutput ("Branch 7", "Float");
            node.CreateOutput ("Branch 8", "Float");

            return node;
        }

        protected internal override void NodeGUI () 
        {
            Inputs[0].DisplayLayout ();

            foreach (NodeOutput output in Outputs)
                output.DisplayLayout ();
        }

        public override bool Calculate () 
        {
            List<NodeOutput> connectedOutputs = new List<NodeOutput> ();
            foreach (NodeOutput output in Outputs)
            { // Get all connected outputs to take into consideration
                output.calculationBlockade = true;
                if (output.connections.Count > 0)
                    connectedOutputs.Add (output);
            }

            if (connectedOutputs.Count > 0)
            { // Select a random branch from the connected ones and unblock it so it gets calculated
                int randomSelected = Random.Range (0, connectedOutputs.Count);
                NodeOutput selectedOutput = connectedOutputs[randomSelected];
                selectedOutput.calculationBlockade = false;
                // Just pass the previous value to the selected branch
                selectedOutput.SetValue (Inputs[0].GetValue ());
            }
            return true;
        }
    }
}

For the sake of completeness, here's the counterpart, where an input gets randomly selected to be the output:

using UnityEngine;
using System.Linq;
using System.Collections.Generic;
using NodeEditorFramework;
using NodeEditorFramework.Utilities;

namespace NodeEditorFramework.Standard
{
    [Node (false, "Example/Random Selector")]
    public class RandomSelectorNode : Node 
    {
        public const string ID = "randomSelectorNode";
        public override string GetID { get { return ID; } }

        public override Node Create (Vector2 pos) 
        {
            RandomSelectorNode node = CreateInstance<RandomSelectorNode> ();

            node.rect = new Rect (pos.x, pos.y, 100, 200);
            node.name = "RND Selector";

            node.CreateInput ("Input 1", "Float");
            node.CreateInput ("Input 2", "Float");
            node.CreateInput ("Input 3", "Float");
            node.CreateInput ("Input 4", "Float");
            node.CreateInput ("Input 5", "Float");
            node.CreateInput ("Input 6", "Float");
            node.CreateInput ("Input 7", "Float");
            node.CreateInput ("Input 8", "Float");

            node.CreateOutput ("Output", "Float");

            return node;
        }

        protected internal override void NodeGUI () 
        {
            Outputs[0].DisplayLayout ();

            foreach (NodeInput input in Inputs)
                input.DisplayLayout ();
        }

        public override bool Calculate () 
        {
            List<NodeInput> connectedInputs = new List<NodeInput> ();
            foreach (NodeInput input in Inputs)
            { // Get all connected inputs to take into consideration
                if (input.connection != null)
                    connectedInputs.Add (input);
            }

            if (connectedInputs.Count > 0)
            { // Select a random input from the connected ones and pass it to the output
                int randomSelected = Random.Range (0, connectedInputs.Count);
                NodeInput selectedInput = connectedInputs[randomSelected];
                // Just pass the previous value to the selected branch
                Outputs[0].SetValue (selectedInput.GetValue ());
            }
            return true;
        }
    }
}

I hope that helps you with your problem!

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

Thanks for all your help. I worked the last days (busy weeks before that, sorry) with that and stumbled upon another odd problem:

I'm trying to plug some references from a scene into the node-graph and don't have a really good solution to that yet. I'm still working on a dialogue-system with your framework and have cases where it would be great to pre/post check some variables in the game manager. Without hard-coding certain variable-checks, it's (either me or really) hard to pre-define actions inside the node graph to get run later on.

I have an Abstract Class like this:

public abstract class AbstractCheckable : MonoBehaviour {
    public abstract bool VariableCheck();
}

And an implementation like this:

public class SomeCheckable : AbstractCheckable {
    public bool isTrue;
    public override bool VariableCheck() {
        return isTrue;
    }
}

And a node like this:

namespace NodeEditorFramework.Standard {
    [System.Serializable]
    [Node(false, "Dialogue/Variable Checker")]
    public class VariableChecker : Node {

    public class VariableChecker : Node {
        public const string ID = "variableChecker";

        public override string GetID {
            get { return ID; }
        }

        public override bool AllowRecursion {
            get { return true; }
        }

        public Node selectedNode;

        [SerializeField]
        private AbstractCheckable _abstractCheckable;

        // Use this for initialization
        public override Node Create(Vector2 pos) {
            VariableChecker node = CreateInstance<VariableChecker>();
            node.rect = new Rect(pos.x, pos.y, 200, 80);

            node.name = "Varibale Check";
            node.CreateInput("Parent", "Void");
            node.CreateOutput("true", "Void");
            node.CreateOutput("false", "Void");
            return node;
        }

        // Update is called once per frame
        protected internal override void NodeGUI() {
            GUILayout.BeginHorizontal ();
            _abstractCheckable = (AbstractCheckable) EditorGUILayout.ObjectField(_abstractCheckable, typeof(AbstractCheckable), true);
            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
            GUILayout.BeginVertical ();
            Inputs[0].DisplayLayout();
            GUILayout.EndVertical();
            GUILayout.BeginVertical();
            Outputs[0].DisplayLayout();
            GUILayout.EndVertical();
            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
            Outputs[1].DisplayLayout();
            GUILayout.EndHorizontal();
        }

        public override bool Calculate() {
            var check = false;
            if (_abstractCheckable != null) {
                Debug.Log("Actually in there.");
                check = _abstractCheckable.VariableCheck();
                selectedNode = check ? Outputs[0].connections[0].body : Outputs[1].connections[0].body;
            }
            return check;
        }
    }
}

I have a demo on a secondary device where this worked fine until I rewrote some irrelevant parts. The inspector reports a TypeMismatch, which is expected with extensions of MonoBehaviour. I'm running out of ideas and probably need to hook up (somewhow?) a singleton + some kind of bridge - or you might have a bright idea on that?

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

It's simply because MonoBehaviours are stored in the scene whereas the canvas is stored as an asset. So it's simply not allowed to reference scene objects:(
I developed a scene saving solution to overcome this problem, you might want to check it out: 23c875b

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

This is in your develop-branch, right?

I have that version right now on my instance, is this the magic "save to scene" button?

How do you use the editor for a field like this: img

Edit: Also I cannot figure out how / what / where it saves that.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

You mean mysterious, and crappy rather than magic? ;) It's a temporary GUI, it's the functionality that counts for now:D

I don't get what it's about, you mean referencing scene objects with the object field or adding knobs with the buttons below?

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

Also, you should not need the calculate button (if it's not something to your design that I don't know about), just make it like this in your Node GUI:

if (GUI.changed)
    NodeEditor.RecalculateFrom (this);

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

No, I actually mean how referencing works (seems my solution works unreliably right now) and how saving to scene works.

I'm still loading my canvas like that:

var _canvas = NodeEditorFramework.NodeEditorSaveManager.LoadNodeCanvas("Assets/Plugins/Node_Editor/Resources/Saves/Boolean_Dialogue.asset", false);

Since saving to scene should make this obsolete - how do I load that now?

The calculate button is just a glorified debug-button.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

Ok, so there is a new API for NodeEditorSaveManager- In order to load from/to the scene, there's now SaveSceneNodeCanvas/ LoadSceneNodeCanvas;) It should be obvious, because parameters are roughly the same. Just note that currently there's no caching for canvases saved in the scene, that means you would loose it by shutting down with unsaved changes:/

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

Interesting. Yet I am not able to load it from scene. Another thing that is probably manageable sooner or later is, that you cannot see already stored canvas.

I'm still confused by this, but loading seems to be working fine. However, the instance-check is still problematic.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

There is a call to GetSceneSaves or something similar, also used by the dropdown to load canvases, which might help you:)
Also, you could modify FetchSceneSaveHolder (again, or similar) to not hide the gameobject holding the saves (the line that modifies hideflags). Make sure to reload the scene an it should show:)
It's basically a set of components differentiated by a name, and saving a canvas with existing name will overwrite that canvas - pretty generic I suppse;)

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

I'm sorry, but there is no drop down. The Node graph I'm using is from the recent commit in the develop branch (23c875b)

Also I'm a bit confused what you mean with your second statement.

Thanks for your patience, tho.

Edit: I just checked again with the abstract-setup and it works fine, finally! There is still the missing dropdown and so on, but I'll figure that out.

I'll write down a reminder and pull-request features to delete inputs/outputs in an efficient way, which looks (for us) like this, for example: https://a.pomf.cat/hfcoqp.mp4

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

No problem:)
The load from scene button has a bug that the dropdown immediately disappears when you click to the right of the button because the dropdown is left-aligned and automatically closes when the mouse is out of reach (which would be immediately the case when it opens out of reach obviously). That causes the dropdown to occasionally not show:/
Also, you'd obviously need atleast one save to see it, too;)

My second statement just describes a method to debug all canvases saved in the scene by showing the location where they are saved (a gameobject, hidden by default). That is if you want to debug it;)

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

I'm still not sure where the dropdown should be. Haha:

The debugging is just to print some internal states of the hackery I'm doing with it.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

Ok maybe I was not too clear lol:D
It's not obvious that it's a dropdown, it's the 'Load from Scene' button which I'm referring too, it will open a dropdown containing every scene save you could load:)
Hope that helps you:) I've to quit unfortunately, where Iive it's like 23:55, so I'll answer tomorrow! :)

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

It's 23:55 here too, you're probably German too, I guess?

Anyway, clicking the "Load from Scene" button doesn't do anything.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

Yep, I'm too in Germany:) I'll take a look at this tomorrow!

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

da3d8b9 adresses this and alot of other errors from the last update:) I can post a gif about using the scene saving functionality in a few mins!

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

Here's the scene saving functionality in a gif:
NESceneSaving
Hope it looks the same for you, as it should;)

from node_editor_framework.

snarlynarwhal avatar snarlynarwhal commented on June 21, 2024

I don't have the option to Save to Scene or Load from Scene - any idea why these options might be missing for me?

capture

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

@pi3butcher Then you're probably using the master branch.
Unfortunately due to lack of time I couldn't yet merge the develop branch with master (develop is way ahead master though and usually even more stable!):/
Sorry for that inconvenience!

Btw, please ask in the forum thread for such questions, I'll usually answer faster there and it'll also not clutter up this issue with offtopic stuff;) Not a big deal though.

from node_editor_framework.

Seneral avatar Seneral commented on June 21, 2024

I suppose this has been resolved? If not, please reopen! Also, I am working on the documentation right now:)

from node_editor_framework.

DarkMio avatar DarkMio commented on June 21, 2024

@Seneral sure is! Very helpful all around.

from node_editor_framework.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.