mcmanning / bluegraph Goto Github PK
View Code? Open in Web Editor NEWVisual Scripting Framework for Unity
License: MIT License
Visual Scripting Framework for Unity
License: MIT License
Could you make a discord channel available for us to communicate?
This would be incredible!
If I close the unity with an open Graph and then re-open the unity, the canvas of the Graph will be null in her GraphEditorWindows.
GraphEditorWindow Line 33:
protected virtual void Update() { Canvas.Update(); //Canvas is NULL }
NullReferenceException: Object reference not set to an instance of an object BlueGraph.Editor.GraphEditorWindow.Update () (at Assets/BlueGraph/BlueGraph-Master/Editor/GraphEditorWindow.cs:33) UnityEditor.HostView.SendUpdate () (at <67055f1be3654e2a987254d5437ee5b8>:0) UnityEditor.EditorApplication.Internal_CallUpdateFunctions () (at <67055f1be3654e2a987254d5437ee5b8>:0)
I just tried to create a condition to reload the chart if it is null, but I was unsuccessful.
When reloading assemblies with a canvas open, the custom search providers added through an override to CreateEditorWindow() aren't being reapplied to the canvas - and it just uses the default search provider. Which is also incorrect for certain use cases if a graph is solely using a custom provider.
To improve forward compatibility, replace Port.isMulti
and Port.isInput
with enums so these can be extended when needed.
Unity has Capacity
and Direction
for GraphView, so basically copy those but usable for runtime graph data.
Graph Attributes:
Node Attributes:
Include Moveable(bool) at NodeAttribute: allow or deny move node at graph.
Big (backwards breaking) refactor so not sure if it makes sense to do:
Currently ports are stored in a single array on AbstractNode and methods more or less assume one array (AddPort, RemovePort, GetPort). Ports themselves know whether or not they're input or output (Port.isInput) which then changes the behavior of methods like GetValue
.
From an optimization standpoint, it doesn't really matter if we're going through a list of 6 ports vs 3 ports to find the right named output. But from a usability standpoint - there's implicit gotchas in the API. E.g. you can't have an output port named the same as an input port, and the behavior of Port.GetValue
changing dramatically based on that isInput
flag.
I think I'm going to make a branch with the change, see what it looks like, and whether or not it makes more sense to do it that way than what I've got currently.
Assets\Samples\ExecGraph\Editor\ExecGraphEditor.cs(5,7): error CS0246: The type or namespace name 'BlueGraphEditor' could not be found (are you missing a using directive or an assembly reference?)
Imported project into Unity2019.3.3 and Unity2020 and got a bunch of these errors.
I'd like to be able to define a port type as a collection container...
class MyNode: ... {
[Input] public SomeCollection<float> foo;
}
... and connect edges into individual slots for that collection, essentially to control the order of inputs.
This wouldn't remove the need for the Port.capacity == Multiple
feature - since I'd still need singular output ports feed to multiple inputs, or single inputs come from multiple outputs without regard for order (e.g. execution flow). But this would improve usability for handling arrays of things.
The associated PortView should expand to include multiple ports, one per connected element.
I'd rather make this a custom collection type to continue supporting a single edge from an output List<T>
to input List<T>
and to add IConvertible support for feeding it into a T[]
or other enumerable.
The other alternative - if this isn't a core feature - is to just have a custom node that accepts a dynamic list of T
inputs and a single T[]
output that compiles them into an array. Will probably add this as an example anyway, but it'd be nice to exist as a core feature.
Is your feature request related to a problem? Please describe.
Bluegraph is a great library, but unfortunately it has a high dependency on Unity, as ScriptableObject and also Json's own serialization is used internally by Unity.
Describe the solution you'd like
Add support for serialization to Json with Newtonsoft or STJ (don't).
Cheers!
the question i have is โhow much do i pay for the convenience of using this graph vs pure c#?โ
a page showing bluegraph vs c# benchmarks would help answer.
considerations: allocation pressure, speed loss, cost of graph traversal, cost of graph instantiation.
tests types:
N=10k which helps evaluate BG impact on CPU starved devices
In typical nodes, like the ones in the examples, which have only input fields but no output fields, these input fields occupy less horizontal space than the editable fields below. This leads to a grey unused area on the right side of a node.
It is of course debatable if this looks good or ugly, but the fact is that this space could be used to make the input fields in an input-only node larger and make use of this space.
Hi MC:
All examples have problems with the node connection. They do not connect from edges to another nodes!
All ports at nodes are invalid to drag drop edge!
Describe the bug
When I create a graph, close unity, and come back to work later, the graph loads and data is missing data.
To Reproduce
Expected behavior
Graph should load with same connections and properties accessible
Screenshots
Close and restart:
Platform (please complete the following information):
Make sure it works on forward Unity builds.
Also figure out if there's some way to do this automatically, because what a pain in the ass. Can I dockerize and run Unity on CircleCI lol.
I am instantiating a graph at runtime and I would like to know how I could go about opening the graph window for this instance.
Support more Unity types in ControlElementFactory.CreateControl
and add support for extending it with custom data types and their associated UIElement editors.
Add a version number baked onto Graph so that migrations can be safely handled in case of backwards breaking changes to how graphs are persisted.
Collections generate garbage USS classes like: type-System-Collections-Generic-List'1[[System-Single, mscorlib, Ver... etc
. Need a better implementation.
The fix will probably be in PortView.AddTypeClasses
and PortView.PortView
when setting the tooltip.
In the dialog example, it seems that there is a grouping feature for nodes. However, when moving the group, it turns out that it's just an empty node around a couple of nodes and doesn't really group them.
So I think that a real grouping feature that treats all nodes in a group as one entity would be very useful since larger graphs quickly become hard to manage. In the best case, such a group should act like a sub-graph with its own inputs and outputs that can be re-used like a function.
Graph undo/redo only tracks a subset of features - but dragging nodes around should definitely be on that list.
Need to figure out if undo should be batched in some way or if it should literally record on every mouse up (and the performance impact on something like that for large graphs).
Describe the bug
when recompile or reopen project, the portMap in the node is empty.
maybe should delete the "portMap = new Dictionary<string, Port>();" in the node Constructor .
CanvasView.m_Search isn't exposed in any way to external usage, so there's no way to call AddSearchProvider
on it while loading a graph with custom providers.
Implement something nice to use - probably just a proxy method on CanvasView
so someone can do something like:
using UnityEditor;
using UnityEngine;
using BlueGraph;
using BlueGraph.Editor;
namespace BlueGraphSamples
{
[CustomEditor(typeof(ExperimentalGraph))]
public class ExperimentalGraphInspector : GraphEditor
{
public override GraphEditorWindow CreateEditorWindow()
{
var window = base.CreateEditorWindow();
window.Canvas.AddSearchProvider(new MyCustomProvider());
return window;
}
}
}
I have a common use case of instantiating graph assets with particular nodes and requiring those nodes to exist at runtime while not exposing them via the search window so that someone cannot add additional instances to the graph.
I add a [Tags("Hidden")]
so that the node doesn't show up in the search, and just do a Graph.AddNode()
in the class constructor of my Graph, but there's nothing to prevent someone from deleting it in the canvas.
This would probably be another field for NodeAttribute
and used solely by the editor to prevent delete actions on that node.
This isn't used at runtime and is only used in the editor for creating a UIElement editable and binding it to the field. Any changes to field names ends up breaking this behavior since during deserialization we expect to map existing ports back to named fields.
Instead - this should be stored on the reflection code to associate named ports to their fields while in the editor. Doing it in reflection should help forward compatibility too if we have some sort of "FormerlyNamed" attribute we can attach to gracefully handle changes.
E.g. to support the following scenario:
[Node]
public class Foo : AbstractNode
{
[Input] public int bar;
}
// Later, I want to refactor my code to make bar -> buzz
[Node]
public class Foo : AbstractNode
{
[FormerlyNamed("Bar")]
[Input] public int buzz;
}
In this hypothetical - the input port named "Bar" can automatically upgrade to "Buzz" and keep the association to the same field and value. It should be able to work alongside Unity's FormerlySerializedAs
.
When dealing with a large selection of nodes, I often find myself also selecting the background comment when I just want to select and move nodes from within a comment container.
Add a shift+click feature that deselects whatever is being clicked on.
Improve migration/stability when code changes are hot reloaded.
Areas to be improved:
[Input] public float foo;
is changed to [Input] public bool foo;
the port remains a float. It needs to change, and also remove connections that are no longer compatible (with plenty of reporting to the developer that this just happened).If we can't magically resolve changes to a node - it'd be nice to insert an "Error Node" placeholder into the graph to indicate what the old node was, what the errors are, and solutions on how to solve it. I can see situations where someone accidentally changes a field type - the "magic" migration code fixes it by deleting all the edges - and then that developer has a hell of a time trying to reconnect everything. And with sufficiently complex graphs, that would be a nightmare.
I think it'd be nice to start off with a graph scanning / validator on hot reload, and then swapping broken nodes for this error node and reporting back the errors for the developer to fix. Once that's in place, we can then identify what errors should be automatically resolved, if any.
Right now the Graph uses a [IncludeModules]
attribute to specify module paths that are allowed to be added through the editor. But I typically run into use cases of Graph A having it's own flow control nodes under /Flow Control
and Graph B also having its own under /Flow Control
. I could rename these to avoid the conflict, but I think a better long term solution would be to just assign a flat list of tags to nodes and have allow/block attributes on a Graph for tags.
This'll also make it easier to implement #3 as we don't need all the extra logic to walk down module paths.
Modules themselves can stay, but it'll just be a representation of how it's listed/grouped in the search results. Maybe renamed to something besides module (just path
or searchPath
?)
Document the recently merged context menu customization feature
Describe the bug
NullReferenceException spam when the editor is rebooted with a BlueGraph editor window still open in the UI. Or if "UI Toolkit Live Reload" is toggled for the editor window.
NullReferenceException: Object reference not set to an instance of an object
BlueGraph.Editor.GraphEditorWindow.Update () (at Library/PackageCache/com.github.mcmanning.bluegraph@9404e1720b/Editor/GraphEditorWindow.cs:33)
UnityEditor.HostView.SendUpdate () (at <3cbc70f1ae9747e88614d75932150c59>:0)
UnityEditor.EditorApplication.Internal_CallUpdateFunctions () (at <3cbc70f1ae9747e88614d75932150c59>:0)
Platform (please complete the following information):
Looks like I'd probably need to build a new canvas instance once it invalidates.
For certain use cases, I'd like to be able to inherit off of Port when defining ports on a node. E.g. to optimize Port.GetValue
by not boxing value types if I can register typed ports.
There's nothing currently preventing Port.Connect from connecting to the same port multiple times outside of the editor itself. Directly calling Port.Connect
or Graph.AddEdge
multiple times will still result in duplicate ports.
A lot of the samples are outdated or incomplete.
ExecGraph and Subgraph are the primary two I want to focus on fleshing out as a basis - since that's the typical UE4-style use case.
Maybe pull my terrain generator stuff and add a subset of those nodes as examples as well - since it demos updating textures / custom NodeView inheritance to show terrain at each step of the process.
And reimplement whatever nodes I had pretty pictures of in the README, since those are pretty ancient by now.
Previously had support for automatic upgrading of nodes marked as [Deprecated]
when a graph is loaded, but it ended up executing far too quickly while working with a graph in the editor (since I used OnBeforeSerialize).
Come up with a better solution and reimplement. For now - the method lives in Graph.UpgradeDeprecatedNodes
but isn't called anywhere.
BUG
When the graph is serialized, any null reference from node or port, used by the user in nodes or graphs will cause errors.
To Reproduce
Create a empty variable for Port, at some Node, Sample:
Port cacheInPort;
Open the graph and create the Node that have this empty reference.
With the graph oppened yet, open theScriptEditor and update somethink and then save it.
Return to unity and wait it refresh.
See error
Screenshots
Follow the Error.
Add your typical edge reroute dots like UE4 and similar graph editors.
Should be able to right click an edge and click an "Add Reroute" button in the context menu to create a reroute node (a hotkey would also be nice to add one under the mouse cursor if we're hovering an edge). They should look like dots matching the color of the edge and can be dragged around and deleted like any other node.
These reroutes would be editor-only and have no effect on the runtime connection info on a Graph. They can be stored in a separate list on the Graph to be persisted, but used only via the editor (like comments, basically).
how do you doing to change the color of the doors? I'm thinking of including a color string (hexadecimal) in the Input, Output attribute.
But before that, I need to know if there is any other implementation!
Will refactor later, as per #5
I had logic to move nodes if the comment that wraps them is moved (UE4-style, essentially) but it's horribly optimized and has a good number of bugs still. I need to just refactor this from the ground up.
Going to remove the behavior for now and reimplement on a later update.
Outputs don't really need to be associated with fields since we don't provide any sort of control element for them, and a lot of the fields declared just to provide [Output]
directives on a node go unused (I always just slap a readonly
on them to stop the linter from complaining).
Maybe it makes sense to also support [Output]
on the class, like:
[Node(module = "Flow Control")]
[Output("Current", typeof(int))]
[Output("Then", typeof(ExecData), multiple = false)]
public class Loop : ExecNode
{
[Input("Count")] public int count;
...
}
Add something equivalent to Unity's OnValidate
for each node, specifically to handle things like assembly reloads while in the editor. Specifically, I want a centralized place for nodes to respond to code changes to update their ports, values, etc etc (potentially to handle #9).
If validation fails, or, honestly, any runtime failures occur - I want a common interface to be able to report that error back to the developer nicely. At a bare minimum, this would throw a node into an error state with an error message string, and the developer can review these errors in context on the canvas.
Errors should also be throwable during assembly reloads and plastered all over the canvas. And if a node isn't open in the canvas, error messages should still be dumped into the debug console so a developer knows they just broke a bunch of graphs by their recent code change.
I'm thinking something like...
OnValidate()
Check NodeReflection for updated IO attributes
Rename / re-type ports to match new definitions
Go into an error state if something cannot be converted safely (type change would break connections, or cannot figure out what something was renamed to)
Put the node into an error state and drop the error message into console
... at which point a developer would need to either fix the code issue to reload assemblies and try OnValidate
again, or open the canvas editor and make the appropriate changes (delete nodes, make new connections, etc)
There are currently no checks in CopyPasteGraph to prevent someone from taking nodes from a graph of one set of [IncludeModules]
and copying them over to another graph with a different [IncludeModules]
.
Simple example:
I have a subgraph defined as:
[IncludeModules("Subgraph", "Flow Control", ...)]
public class Subgraph : Graph
{
...
}
I can copy+paste any nodes from that over to another graph without checking IncludeModules first:
[IncludeModules("UAI")]
public class UtilityAI : Graph
{
...
}
There's a conflict between the rules of the CopyPasteGraph and the search providers. If I hide nodes from DefaultSearchProvider
, e.g. by tagging them as something not in a Graph's [IncludeTags]
, the CopyPasteGraph will also exclude these nodes when reapplying them onto the graph. So all copy/paste/duplicate operations don't work.
I'd like to be able to denote that a node is hidden from the default search provider but can still be used on a graph, preferably by not just giving it a tag that isn't in [IncludeTags]
.
When dragging off a port and connecting a new node - it doesn't prefer ports of the same type over other ports that can accept the value. Instead it just picks the "first" that works.
Use Case: I have an execution flow data type on nodes - but some nodes accept any basic object
type (e.g. debug loggers). Since that object type port was added to the node first, it's the first to respond to the request for a connection when instantiating a new node thus creates an incorrect connection.
Instead - the logic should be something like:
But is it still alive?
You can currently open a graph multiple times and have unsynced views of the same graph.
There's a TODO stubbed out in GraphEditor.ShowGraphEditor
for this. Rather than instantiating a new one it should just focus an existing window if one exists.
Adding to initial release priority list since this could cause some nondeterministic behavior when editing a graph.
For a lot of nodes the initial paint time when loading a graph is pretty horrid. Would be nice to replace this with something a bit more batched.
It has been a long time since I stopped contributing to this package, but I look forward to returning.
I am in doubt about how stable your package is currently.
I'm looking to use it for my current project, almost in Alpha phase. I will automatically contribute to its development again. But I looked at the update logs and noticed it has been down for over a year.
Can you please confirm for me if everything is working fine around here?
Sorry to send a message here, I don't remember if I have your personal contact or DISCORD...
If it is of interest to you, I would love to have you Discord contact! I'm waiting. Hugs!
Fill the wiki with documentation, examples, and horrible grammar.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.