Determine node location for flow-chart style script/event editor

This one isn’t really a specific monogame question, but I’d appreciate any help that can be offered.

So I’m working on a level/game editor at the moment. I’ve determined
that I want to try using a flow-chart style scripting editor to
visually represent the type of things that can occur(Move-Character,
Dialogue, etc). There will also be conditional nodes that branch the
chart.

I’m having a bit of difficulty finding information and thinking of
how to determine the positioning of the nodes. Specifically, when a
branch occurs, how to determine where to put those nodes and to ensure no overlapping occurs.

The structure of the node is pretty simple right now. It has an ID,
and then it also stores the ID of its child nodes.

I’ve thought about manually placing the nodes and storing the X,Y coords when I serialize it to XML, but I’d prefer to use an algorithm to place them if possible.

Are you trying to build a node editor directly with the Monogame.Framework or are you just searching for a way to connect MonoGame specific stuff (and your own) with an existing node editor solution?

Some time ago I made an inhouse tool which uses https://github.com/Microsoft/automatic-graph-layout . Personally I don’t like it very much, but beats writing my own and you may take ideas from the source, or even reuse it (it is not Monogame-ready though)

1 Like

The samples look pretty good!

In my experience these layout tools never work for all cases though and I like to have the possibility of moving the nodes myself. Still a nice initial position is great to have.

Actually you can move the nodes around. The problem was (I wrote the tool almost two years ago) that when I wanted to add a new node, the whole layout was computed again and you lost all the ‘movement changes’. And sometimes adding a new node (specially if it’s connected to several other nodes) can change the layout radically, so saving and reloading positions is not always possible and you end up with a considerable mess.

But as I said, this was almost two years ago. Things may have changed.

1 Like

In my opinion the best possible library, which is both efficient and fun to use is:

It supports multiple execution pathes, conditional nodes, loops and so on and it perfectly harmonizes with MonoGame or general C# development.

BTW: I successfully use it together with my library MonoGame.Forms. It’s even possible to have a MonoGame render control inside the NodeGraph (custom user control support), without interupting the whole process.

2 Likes

Thanks for the replies everyone! Both of those projects look interesting, and I’ll definitely take a look at them. At the very least the source should help give me an idea of the direction to go.

So I’ve been playing around with this for a bit, and it seems pretty cool. I managed to get it to show the nodes for the “events” I have, along with the properties.

One thing I couldn’t quite wrap my head around was how to get it to add to my List. The basic structure I have right now, is that any “event” in the game has its own class(So dialogue, move-to, etc). I store it in a List and use that list to determine what to run at run-time.

I figured that, in order to add to that list, I would simply call list.Add in the FContext class, as follows:

 [Node(name: "Dialogue", menu: "Events", customEditor: typeof(Dialogue), description: "Testing")]
        public void Dialogue(string text, Vector2 position, out Dialogue dialogue)
        {
            dialogue = new Dialogue();
            dialogue.text = text;
            dialogue.pos = position;
            gameEvents.Add(dialogue);
        }

Do you have any ideas, or maybe a better way to do this on my end?

I just use “strip” and “stack” packing done manually (have to select a command to run the pack) going upstream (the direction I happen to care about). I also only apply it along pure data-graphs that are data and don’t trace along flow-control connections (although the images below are pure data only, there’s others that are more Blueprint’y).

In SprueTex I didn’t bother as texture graphs tend to get cluttered up anyways so I prioritized other organizational tools (warps, line-control, sections/groups) instead of layout - it was also more problematic because the preview sizes are customizable for 64x64 or 128x128 which can make a bit of a mess out of everything.

Strip Pack

Upstream parameters are sprawled out. Note, fudging puts the uniform in an undesirable location, without the fudge other subtrees would overlap if things were deep enough.

Stack Pack

Upstream parameters are indented under the node the pack began from. This is my preferred form as the graph is compact and still easy to interpret.

Yeah, you can handle it like that and then create the final dialogue tree and use it in custom classes for further processing:

public event Action<List<Dialogue>> CreateDialogueTree= delegate { };

[Node(name:"CreateDialogeTree", menu:"General", false, true)]
public void Create(List<Dialogue> dialogueTree)
{
    CreateDialogueTree?.Invoke(dialogueTree);
}

To work with generic lists in the NodeGraph you need to apply a small patch to the library in the NodesControl.cs class:

private Assembly AssemblyResolver(AssemblyName assemblyName)
{
    return AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.GetName().ToString() == assemblyName.FullName);
}

It’s located here.

If you somehow need Array support as input nodes in the NodeGraph I can help you to apply the patches at the right places as well, because this feature is not available in the original NodeEditor on GitHub.

Thank you! I’ll mess around with it and see what I can come up with!

1 Like