Add a Select node that picks one of two values by a condition
Choosing between two values meant a Branch with the whole action twice behind it, for example two Play animation nodes that differ only in the animation. Every later change had to be made in both. Select picks the value, so the action stays single. - Select is a data node with the inputs condition, false and true and the output value. It passes on "true" if the condition holds, else "false". An unconnected condition counts as false, and an empty picked input gives null. - The ports are named false and true, not a and b, so nobody has to guess which input is which. The order false, true follows Unreal's Select and Blender's Switch. - false, true and value share one type through `sharedType`, like First not empty. With two Animation literals plugged in, value takes their type and fits Play animation directly. - Both inputs are always evaluated. Data nodes have no side effects, so that does not matter. Tests: - ./check.sh: 160 files, 2363 tests, CHECK EXIT 0 (before 2356). - 5 cases in tests/core/node-catalog.test.ts and 2 in tests/core/shared-port-type.test.ts. - Counter checks: with the inputs swapped all 5 catalog cases fail, without sharedType exactly the type test fails. - No e2e change, the sum stays at 1380. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
89048413f1
commit
5dbac3a8df
4 files changed
+77
No files matched your search
@@ -843,6 +843,29 @@ const CASES: Record<string, Case[]> = {
|
||||
outputs: { value: 5 },
|
||||
},
|
||||
],
|
||||
Select: [
|
||||
{
|
||||
name: 'true takes the true input',
|
||||
inputs: { condition: true, false: 'Idle', true: 'Walk' },
|
||||
outputs: { value: 'Walk' },
|
||||
},
|
||||
{
|
||||
name: 'false takes the false input',
|
||||
inputs: { condition: false, false: 'Idle', true: 'Walk' },
|
||||
outputs: { value: 'Idle' },
|
||||
},
|
||||
{ name: 'an unconnected condition is false', inputs: { false: 1, true: 2 }, outputs: { value: 1 } },
|
||||
{
|
||||
name: 'an empty picked input gives null',
|
||||
inputs: { condition: true, false: 1 },
|
||||
outputs: { value: null },
|
||||
},
|
||||
{
|
||||
name: 'a value is passed on as it is, even an empty one',
|
||||
inputs: { condition: false, false: 0, true: 5 },
|
||||
outputs: { value: 0 },
|
||||
},
|
||||
],
|
||||
And: [
|
||||
{ name: 'both true', inputs: { a: true, b: true }, outputs: { result: true } },
|
||||
{ name: 'one false', inputs: { a: true, b: false }, outputs: { result: false } },
|
||||
|
||||
@@ -133,6 +133,40 @@ describe('First not empty, whose a, b and value carry the same value', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Select, whose false, true and value carry the same value', () => {
|
||||
it('takes the type of its two value inputs, and the condition has no say in it', () => {
|
||||
const f = fixture();
|
||||
const node = f.edit.addNode('Select');
|
||||
f.edit.connect(f.edit.addNode('Boolean'), 'value', node, 'condition');
|
||||
const idle = f.edit.addNode('Animation');
|
||||
f.edit.connect(idle, 'value', node, 'false');
|
||||
expect(typeOf(f.behavior, node, 'value', f)).toBe('any');
|
||||
|
||||
f.edit.connect(f.edit.addNode('Animation'), 'value', node, 'true');
|
||||
const animation = typeOf(f.behavior, idle, 'value', f);
|
||||
expect(animation).not.toBe('any');
|
||||
expect(typeOf(f.behavior, node, 'value', f)).toBe(animation);
|
||||
});
|
||||
|
||||
it('then fits the animation input of Play animation, as each of its inputs would', () => {
|
||||
const f = fixture();
|
||||
const node = f.edit.addNode('Select');
|
||||
f.edit.wire([
|
||||
[f.edit.addNode('Animation'), 'value', node, 'false'],
|
||||
[f.edit.addNode('Animation'), 'value', node, 'true'],
|
||||
]);
|
||||
const play = f.edit.addNode('PlayAnimation');
|
||||
const lookup = graphLookup(f.project);
|
||||
const out = portTypeOf(f.behavior.graph, { nodeId: node.id, port: 'value', isOutput: true }, lookup)!;
|
||||
const inp = portTypeOf(
|
||||
f.behavior.graph,
|
||||
{ nodeId: play.id, port: 'animation', isOutput: false },
|
||||
lookup,
|
||||
)!;
|
||||
expect(portsCompatible(out, inp)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
/** As the canvas draws it: `drawnDef` is the only place a pin colour is decided. */
|
||||
const inputPin = (behavior: BehaviorAsset, node: GraphNode, key: string, f: ProjectFixture): PortDef => {
|
||||
const lookup = graphLookup(f.project);
|
||||
|
||||
Reference in new issue
Block a user