Let a behavior be a node in another graph
A behavior that has a Start and an End node can now be dropped into any other graph as a node of its own. What is declared on the start node becomes the inputs of that node, what hangs on the end node its outputs; the port list is derived from the sub graph, not copied, so declaring a port in one graph grows the node in the other without touching it. The node carries the behavior's name and the palette lists behaviors by name, so a call is one grab instead of a node plus a dropdown. An embedded behavior has no object and therefore no place for variables: every call starts on the asset defaults and communicates only through its ports. That is the conservative direction - state can still be added later, and shared state already has a home in a behavior object in the scene. Node ids are unique per graph only, so each call gets its own pulse cache; without that, two graphs would collide. Renaming a port used to silently drop the value typed on the calling node. It is carried along now, project wide, like the edges.
This commit is contained in:
1 parent
64e034ffb9
commit
6702ff8abe
31 files changed
+1402
-107
No files matched your search
@@ -18,6 +18,7 @@ import {
|
||||
dropTargetPort,
|
||||
findNode,
|
||||
firstPortFor,
|
||||
NO_BEHAVIORS,
|
||||
type PortType,
|
||||
portsCompatible,
|
||||
requireNodeDef,
|
||||
@@ -512,7 +513,7 @@ describe('dropping an edge on a node', () => {
|
||||
it('picks the first compatible input', () => {
|
||||
const { graph, number, clamp } = fixtureWithClamp();
|
||||
const from = { nodeId: number.id, port: 'value', isOutput: true };
|
||||
expect(dropTargetPort(graph, from, clamp.id)).toEqual({
|
||||
expect(dropTargetPort(graph, from, clamp.id, NO_BEHAVIORS)).toEqual({
|
||||
nodeId: clamp.id,
|
||||
port: 'value',
|
||||
isOutput: false,
|
||||
@@ -524,7 +525,7 @@ describe('dropping an edge on a node', () => {
|
||||
const other = edit.addNode('Number');
|
||||
edit.connect(other, 'value', clamp, 'value');
|
||||
const from = { nodeId: number.id, port: 'value', isOutput: true };
|
||||
expect(dropTargetPort(graph, from, clamp.id)?.port).toBe('min');
|
||||
expect(dropTargetPort(graph, from, clamp.id, NO_BEHAVIORS)?.port).toBe('min');
|
||||
});
|
||||
|
||||
it('falls back to the last compatible input once every one is taken', () => {
|
||||
@@ -532,7 +533,7 @@ describe('dropping an edge on a node', () => {
|
||||
for (const port of ['value', 'min', 'max']) edit.connect(edit.addNode('Number'), 'value', clamp, port);
|
||||
const from = { nodeId: number.id, port: 'value', isOutput: true };
|
||||
// Not free, but the drop still connects – it replaces the edge, as dropping on the port would.
|
||||
expect(dropTargetPort(graph, from, clamp.id)?.port).toBe('max');
|
||||
expect(dropTargetPort(graph, from, clamp.id, NO_BEHAVIORS)?.port).toBe('max');
|
||||
});
|
||||
|
||||
it('keeps offering an exec input, which is never exclusive', () => {
|
||||
@@ -543,26 +544,26 @@ describe('dropping an edge on a node', () => {
|
||||
const move = edit.addNode('SetPosition');
|
||||
edit.connect(edit.addNode('OnKeyHeld'), 'exec', move, 'exec');
|
||||
const from = { nodeId: held.id, port: 'exec', isOutput: true };
|
||||
expect(dropTargetPort(behavior.graph, from, move.id)?.port).toBe('exec');
|
||||
expect(dropTargetPort(behavior.graph, from, move.id, NO_BEHAVIORS)?.port).toBe('exec');
|
||||
});
|
||||
|
||||
it('refuses a node that offers nothing compatible, and the node itself', () => {
|
||||
const { graph, edit, number, clamp } = fixtureWithClamp();
|
||||
const boolean = edit.addNode('Boolean');
|
||||
const from = { nodeId: number.id, port: 'value', isOutput: true };
|
||||
expect(dropTargetPort(graph, from, boolean.id)).toBeNull();
|
||||
expect(dropTargetPort(graph, from, number.id)).toBeNull();
|
||||
expect(dropTargetPort(graph, from, boolean.id, NO_BEHAVIORS)).toBeNull();
|
||||
expect(dropTargetPort(graph, from, number.id, NO_BEHAVIORS)).toBeNull();
|
||||
// A pair that is already wired is not offered again either.
|
||||
edit.connect(number, 'value', clamp, 'value');
|
||||
edit.connect(number, 'value', clamp, 'min');
|
||||
edit.connect(number, 'value', clamp, 'max');
|
||||
expect(dropTargetPort(graph, from, clamp.id)).toBeNull();
|
||||
expect(dropTargetPort(graph, from, clamp.id, NO_BEHAVIORS)).toBeNull();
|
||||
});
|
||||
|
||||
it('resolves a drag started at an input to an output', () => {
|
||||
const { graph, number, clamp } = fixtureWithClamp();
|
||||
const from = { nodeId: clamp.id, port: 'value', isOutput: false };
|
||||
expect(dropTargetPort(graph, from, number.id)).toEqual({
|
||||
expect(dropTargetPort(graph, from, number.id, NO_BEHAVIORS)).toEqual({
|
||||
nodeId: number.id,
|
||||
port: 'value',
|
||||
isOutput: true,
|
||||
|
||||
Reference in new issue
Block a user