Skip to content

Commit

Permalink
Add flow nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
lexaknyazev committed Feb 26, 2024
1 parent 4b7b4fe commit 866ea7f
Showing 1 changed file with 236 additions and 0 deletions.
236 changes: 236 additions & 0 deletions extensions/2.0/Khronos/KHR_interactivity/Specification.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1523,3 +1523,239 @@ a ? (31 - Math.clz32(a & -a)) : 32;
|===

If stem:[a] is 0, the operation returns 0; if stem:[a] is -1, the operation returns 32.

=== Control Flow Nodes

==== Sync Nodes

===== Sequence

[cols="1h,1,2"]
|===
| Type | `flow/sequence` | Sequentially activate all connected output flows
| Input flow sockets
| `in` | The entry flow into this node
| Output flow sockets
| `<i>` | The `i`-th output flow, `i` is a non-negative integer decimal number less than or equal to 2147483647.
|===

This node has no internal state.

When the `in` input flow is activated:

1. Let a temporary variable `index` be -1.
2. Let a temporary variable `maxIndex` be the maximum output flow name value.
3. If `index` is less than `maxIndex`:
.. increment `index` by 1;
.. activate the output flow named `<index>` if it exists and is connected;
.. goto step 3.

===== Branch

[cols="1h,1,2"]
|===
| Type | `flow/branch` | Branch the execution flow based on a condition
| Input flow sockets
| `in` | The entry flow into this node
| Input value sockets
| `bool condition` | Value selecting the branch taken
.2+| Output flow sockets
| `true` | The flow to be activated if the `condition` input value is true
| `false` | The flow to be activated if the `condition` input value is false
|===

This node has no internal state.

The `condition` input value is evaluated each time the node is executed.

===== Switch

[cols="1h,1,2"]
|===
| Type | `flow/switch` | Conditionally route the execution flow to one of the outputs
| Configuration
| `int[] cases` | The cases on which to perform the switch on; values **MUST** be unique integers
| Input flow sockets
| `in` | The entry flow into this node
| Input value sockets
| `int selection` | The value on which the switch operates
.2+| Output flow sockets
| `<i>` | The `i`-th output flow, `i` is an integer decimal number; it **MUST** be present in the `cases` configuration
| `default` | The output flow used when the `selection` input value is not present in the `cases` configuration
|===

This node has no internal state.

When the `in` input flow is activated:

1. Evaluate the `selection` input value.
2. If the `cases` configuration array does not contain the `selection` input value:
.. activate the `default` output flow if it is connected.
3. If the `cases` configuration array contains the `selection` input value:
.. activate the output flow named `<selection>` if it is connected.

===== While Loop

[cols="1h,1,2"]
|===
| Type | `flow/while` | Repeatedly activate the output flow based on a condition
| Input flow sockets
| `in` | The entry flow into this node
| Input value sockets
| `bool condition` | Loop condition
.2+| Output flow sockets
| `loopBody` | The flow to be activated while the `condition` input value is true
| `completed` | The flow to be activated once the `condition` input value is false
|===

This node has no internal state.

When the `in` input flow is activated:

1. Evaluate the `condition`. The `condition` **MUST NOT** statically evaluate to true, otherwise the node is invalid.
2. If the `condition` is true,
.. activate the `loopBody` output flow;
.. after completion of the `loopBody` output flow, goto step 1.
3. If the `condition` is false,
.. activate the `completed` output flow.

===== For Loop

[cols="1h,1,2"]
|===
| Type | `flow/for` | Repeatedly activate the output flow based on an incrementing index value
| Configuration
| `int initialIndex` | The index value before the loop starts
| Input flow sockets
| `in` | The entry flow into this node
.2+| Input value sockets
| `int startIndex` | The start index of the loop
| `int endIndex` | The end index of the loop
.2+| Output flow sockets
| `loopBody` | The flow to be activated if the `index` value is less than the `endIndex` input value
| `completed` | The flow to be activated if the `index` value is greater than or equal to the `endIndex` input value
| Output value sockets
| `int index` | The current index value if the node has ever been activated, `initialIndex` otherwise
|===

The internal state of this node consists of one 32-bit signed integer value `index` initialized to `initialIndex`.

When the `in` input flow is activated:

1. Evaluate the `startIndex` input value.
2. Set `index` to `startIndex`.
3. Evaluate the `endIndex` input value.
4. If `index` is less than the `endIndex` input value,
.. activate the `loopBody` output flow;
.. after completion of the `loopBody` output flow, increment the `index` value by 1;
.. goto step 3.
5. If the `index` value is greater than or equal to the `endIndex` input value,
.. activate the `completed` output flow.

===== Do N

[cols="1h,1,2"]
|===
| Type | `flow/doN` | Activate the output flow no more than N times
.2+| Input flow sockets
| `in` | The entry flow into this node
| `reset` | When this flow is activated, the `currentCount` value is reset to 0
| Input value sockets
| `int n` | Maximum number of times the `out` output flow is activated
| Output flow sockets
| `out` | The flow to be activated if the `currentCount` value is less than the `n` input value
| Output value sockets
| `int currentCount` | The current execution count
|===

The internal state of this node consists of one 32-bit signed integer value `currentCount` initialized to 0.

When the `reset` input flow is activated:

1. Reset `currentCount` to 0.

When the `in` input flow is activated:

1. Evaluate the `n` input value.
2. If `currentCount` is less than `n`,
.. increment `currentCount` by 1;
.. activate the `out` output flow.

===== Multi Gate

[cols="1h,1,2"]
|===
| Type | `flow/multiGate` | Route the execution flow to one of the outputs sequentially or randomly
.3+| Configuration
| `int outputFlows` | The number of output flows, **MUST** be greater than 0
| `bool isRandom` | If set to true, output flows are executed in random order, picking a random not used output flow each time until all are done
| `bool loop` | If set to true, the outputs will repeat in a loop continuously after all are done
.2+| Input flow sockets
| `in` | The entry flow into this node
| `reset` | When this flow is activated, the `lastIndex` value is reset to -1 and all outputs are marked as not used
| Output flow sockets
| `<i>` | The `i`-th output flow, `i` is a non-negative integer decimal number less than the `outputFlows` configuration value
| Output value sockets
| `int lastIndex` | The index of the last used output; `-1` if the node has not been activated
|===

The internal state of this node consists of one 32-bit signed integer value `lastIndex` initialized to -1 and a map of booleans with all values initialized to false representing used output flows. The size of the boolean map is equal to the number of connected output flows, i.e., unconnected output flows are ignored.

When the `reset` input flow is activated:

1. Reset the `lastIndex` value to -1.
2. Mark all connected output flows as not used in the boolean map.

When the `in` input flow is activated:

1. If the `isRandom` input value is false,
.. let `i` be the smallest connected not used output flow index according to the boolean map or -1 if all flows are marked as used.
2. If the `isRandom` input value is true,
.. let `i` be a random not used connected output flow index according to the boolean map or -1 if all flows are marked as used.
3. If `i` is greater than -1,
.. mark the `i`-th output as used in the boolean map;
.. set the `lastIndex` value to `i`;
.. activate the output flow `i`.
4. If `i` is equal to -1 and the `loop` input value is true,
.. mark all connected output flows as not used in the boolean map;
.. if the `isRandom` input value is false,
... set `i` to the smallest connected output flow index;
.. if the `isRandom` input value is true,
... set `i` be a random connected output flow index;
.. mark the `i`-th output flow as used in the boolean map;
.. set the `lastIndex` value to `i`;
.. activate the output flow `i`.

===== Wait All

[cols="1h,1,2"]
|===
| Type | `flow/waitAll` | Activate the output flow when all input flows have been activated at least once.
| Configuration
| `int inputFlows` | The number of input flows, **MUST** be greater than 0
.2+| Input flow sockets
| `<i>` | The `i`-th input flow, `i` is a non-negative integer decimal number less than the `inputFlows` configuration value
| `reset` | When this flow is activated, all input flows are marked as unused
.2+| Output flow sockets
| `out` | The flow to be activated after every input flow activation except the last missing input
| `completed` | The flow to be activated when the last missing input flow is activated
| Output value sockets
| `int remainingInputs` | The number of not yet activated input flows
|===

The internal state of this node consists of one 32-bit signed integer value `remainingInputs` initialized to the number of connected input flows not including the `reset` input flow and a map of booleans with all values initialized to false representing used input flow sockets. The size of the boolean map is equal to the initial `remainingInputs` value.

When the `reset` input flow is activated:

1. Reset `remainingInputs` to the number of connected input flows not including the `reset` input flow.
2. Mark all connected input flows as not used in the boolean map.

When any of the `<i>` input flows is activated:

1. If the `<i>`-th input flow is not marked as used in the boolean map:
.. mark the `<i>`-th input flow as used in the boolean map.
.. decrement the `remainingInputs` value by 1;
2. If the `remainingInputs` value is zero:
.. activate the `completed` output flow.
3. If the `remainingInputs` value is not zero:
.. activate the `out` output flow.

0 comments on commit 866ea7f

Please sign in to comment.