@aura3d/scripting 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +32 -2
- package/src/AdaptiveDifficultyFixtures.ts +0 -324
- package/src/AnalyticsPrivacyFixtures.ts +0 -182
- package/src/AnimationNodeCategories.ts +0 -10
- package/src/AnimationVisualNodes.ts +0 -44
- package/src/Behavior.ts +0 -11
- package/src/BehaviorHost.ts +0 -51
- package/src/BehaviorRegistry.ts +0 -22
- package/src/BehaviorSystem.ts +0 -103
- package/src/BehaviorTree.ts +0 -234
- package/src/CloudServiceFixtures.ts +0 -225
- package/src/CulturalBehaviorFixtures.ts +0 -262
- package/src/DecisionTree.ts +0 -162
- package/src/GOAP.ts +0 -150
- package/src/HTN.ts +0 -178
- package/src/LearningAgentFixtures.ts +0 -184
- package/src/NetworkReplicationFixtures.ts +0 -440
- package/src/Perception.ts +0 -163
- package/src/PlayerBehaviorTelemetryFixtures.ts +0 -257
- package/src/ProceduralContentAdaptationFixtures.ts +0 -205
- package/src/ScriptContext.ts +0 -34
- package/src/StateMachine.ts +0 -138
- package/src/UtilityAI.ts +0 -158
- package/src/VisualGraph.ts +0 -236
- package/src/VisualGraphContext.ts +0 -138
- package/src/VisualGraphExecutor.ts +0 -709
- package/src/VisualNode.ts +0 -44
- package/src/VisualNodeCatalog.ts +0 -202
- package/src/WeaponSystem.ts +0 -793
- package/src/index.ts +0 -178
- package/tests/scripting.test.ts +0 -253
- package/tsconfig.json +0 -7
package/src/UtilityAI.ts
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import type { Blackboard } from "./BehaviorTree";
|
|
2
|
-
|
|
3
|
-
export type UtilityCurve = "linear" | "inverse" | "quadratic" | "cubic" | "boolean" | "logistic";
|
|
4
|
-
export type UtilityScoring = "multiply" | "average" | "min" | "max" | "sum";
|
|
5
|
-
|
|
6
|
-
export interface UtilityContext {
|
|
7
|
-
readonly blackboard?: Blackboard;
|
|
8
|
-
readonly values?: Record<string, number | boolean | string | undefined>;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface UtilityConsiderationOptions {
|
|
12
|
-
readonly name: string;
|
|
13
|
-
readonly input: (context: UtilityContext) => number | boolean;
|
|
14
|
-
readonly curve?: UtilityCurve;
|
|
15
|
-
readonly weight?: number;
|
|
16
|
-
readonly threshold?: number;
|
|
17
|
-
readonly slope?: number;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface UtilityActionOptions {
|
|
21
|
-
readonly name: string;
|
|
22
|
-
readonly considerations: readonly UtilityConsideration[];
|
|
23
|
-
readonly scoring?: UtilityScoring;
|
|
24
|
-
readonly baseScore?: number;
|
|
25
|
-
readonly enabled?: boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface UtilityActionScore {
|
|
29
|
-
readonly action: string;
|
|
30
|
-
readonly score: number;
|
|
31
|
-
readonly considerationScores: Record<string, number>;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class UtilityConsideration {
|
|
35
|
-
readonly name: string;
|
|
36
|
-
readonly curve: UtilityCurve;
|
|
37
|
-
readonly weight: number;
|
|
38
|
-
readonly threshold: number;
|
|
39
|
-
readonly slope: number;
|
|
40
|
-
private readonly input: (context: UtilityContext) => number | boolean;
|
|
41
|
-
|
|
42
|
-
constructor(options: UtilityConsiderationOptions) {
|
|
43
|
-
this.name = options.name;
|
|
44
|
-
this.input = options.input;
|
|
45
|
-
this.curve = options.curve ?? "linear";
|
|
46
|
-
this.weight = options.weight ?? 1;
|
|
47
|
-
this.threshold = options.threshold ?? 0.5;
|
|
48
|
-
this.slope = options.slope ?? 10;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
evaluate(context: UtilityContext): number {
|
|
52
|
-
const raw = this.input(context);
|
|
53
|
-
const value = typeof raw === "boolean" ? (raw ? 1 : 0) : clamp01(raw);
|
|
54
|
-
return round3(clamp01(applyCurve(value, this.curve, this.threshold, this.slope) * this.weight));
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export class UtilityAction {
|
|
59
|
-
readonly name: string;
|
|
60
|
-
readonly considerations: readonly UtilityConsideration[];
|
|
61
|
-
readonly scoring: UtilityScoring;
|
|
62
|
-
readonly baseScore: number;
|
|
63
|
-
enabled: boolean;
|
|
64
|
-
|
|
65
|
-
constructor(options: UtilityActionOptions) {
|
|
66
|
-
this.name = options.name;
|
|
67
|
-
this.considerations = options.considerations;
|
|
68
|
-
this.scoring = options.scoring ?? "multiply";
|
|
69
|
-
this.baseScore = options.baseScore ?? 0;
|
|
70
|
-
this.enabled = options.enabled ?? true;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
score(context: UtilityContext): UtilityActionScore {
|
|
74
|
-
const considerationScores = Object.fromEntries(this.considerations.map((consideration) => [consideration.name, consideration.evaluate(context)]));
|
|
75
|
-
const values = Object.values(considerationScores);
|
|
76
|
-
const combined = values.length === 0 ? 0 : combineScores(values, this.scoring);
|
|
77
|
-
return {
|
|
78
|
-
action: this.name,
|
|
79
|
-
score: round3(clamp01(combined + this.baseScore)),
|
|
80
|
-
considerationScores
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export class UtilityAI {
|
|
86
|
-
private readonly actions: UtilityAction[] = [];
|
|
87
|
-
|
|
88
|
-
addAction(action: UtilityAction): void {
|
|
89
|
-
if (this.actions.some((entry) => entry.name === action.name)) {
|
|
90
|
-
throw new Error(`Utility action already registered: ${action.name}`);
|
|
91
|
-
}
|
|
92
|
-
this.actions.push(action);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
removeAction(name: string): boolean {
|
|
96
|
-
const index = this.actions.findIndex((action) => action.name === name);
|
|
97
|
-
if (index < 0) return false;
|
|
98
|
-
this.actions.splice(index, 1);
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
setActionEnabled(name: string, enabled: boolean): void {
|
|
103
|
-
const action = this.actions.find((entry) => entry.name === name);
|
|
104
|
-
if (!action) throw new Error(`Utility action is not registered: ${name}`);
|
|
105
|
-
action.enabled = enabled;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
evaluate(context: UtilityContext): readonly UtilityActionScore[] {
|
|
109
|
-
return this.actions
|
|
110
|
-
.filter((action) => action.enabled)
|
|
111
|
-
.map((action) => action.score(context))
|
|
112
|
-
.sort((left, right) => right.score - left.score || left.action.localeCompare(right.action));
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
select(context: UtilityContext): UtilityActionScore | undefined {
|
|
116
|
-
return this.evaluate(context)[0];
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function combineScores(values: readonly number[], scoring: UtilityScoring): number {
|
|
121
|
-
switch (scoring) {
|
|
122
|
-
case "average":
|
|
123
|
-
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
124
|
-
case "min":
|
|
125
|
-
return Math.min(...values);
|
|
126
|
-
case "max":
|
|
127
|
-
return Math.max(...values);
|
|
128
|
-
case "sum":
|
|
129
|
-
return Math.min(1, values.reduce((sum, value) => sum + value, 0));
|
|
130
|
-
case "multiply":
|
|
131
|
-
return values.reduce((product, value) => product * value, 1);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function applyCurve(value: number, curve: UtilityCurve, threshold: number, slope: number): number {
|
|
136
|
-
switch (curve) {
|
|
137
|
-
case "inverse":
|
|
138
|
-
return 1 - value;
|
|
139
|
-
case "quadratic":
|
|
140
|
-
return value * value;
|
|
141
|
-
case "cubic":
|
|
142
|
-
return value * value * value;
|
|
143
|
-
case "boolean":
|
|
144
|
-
return value >= threshold ? 1 : 0;
|
|
145
|
-
case "logistic":
|
|
146
|
-
return 1 / (1 + Math.exp(-slope * (value - threshold)));
|
|
147
|
-
case "linear":
|
|
148
|
-
return value;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function clamp01(value: number): number {
|
|
153
|
-
return Math.max(0, Math.min(1, Number.isFinite(value) ? value : 0));
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function round3(value: number): number {
|
|
157
|
-
return Number(value.toFixed(3));
|
|
158
|
-
}
|
package/src/VisualGraph.ts
DELETED
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import { validateNode, type VisualNode } from "./VisualNode";
|
|
2
|
-
import { getVisualNodeDefinition } from "./VisualNodeCatalog";
|
|
3
|
-
import {
|
|
4
|
-
type VisualGraphExecutionContext,
|
|
5
|
-
type VisualGraphValidationOptions,
|
|
6
|
-
type VisualStateCollection
|
|
7
|
-
} from "./VisualGraphContext";
|
|
8
|
-
|
|
9
|
-
export interface VisualEdge {
|
|
10
|
-
readonly fromNode: string;
|
|
11
|
-
readonly fromPort: string;
|
|
12
|
-
readonly toNode: string;
|
|
13
|
-
readonly toPort: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface VisualGraph {
|
|
17
|
-
readonly nodes: readonly VisualNode[];
|
|
18
|
-
readonly edges: readonly VisualEdge[];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export type SerializedVisualGraph = {
|
|
22
|
-
readonly nodes: readonly VisualNode[];
|
|
23
|
-
readonly edges: readonly VisualEdge[];
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export function validateGraph(graph: VisualGraph, options: VisualGraphValidationOptions = {}): readonly string[] {
|
|
27
|
-
const errors: string[] = [];
|
|
28
|
-
const nodes = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
29
|
-
const seenNodeIds = new Set<string>();
|
|
30
|
-
|
|
31
|
-
for (const node of graph.nodes) {
|
|
32
|
-
if (seenNodeIds.has(node.id)) {
|
|
33
|
-
errors.push(`Duplicate node id: ${node.id}`);
|
|
34
|
-
}
|
|
35
|
-
seenNodeIds.add(node.id);
|
|
36
|
-
errors.push(...validateNode(node));
|
|
37
|
-
const definition = getVisualNodeDefinition(node.kind);
|
|
38
|
-
if (!definition) {
|
|
39
|
-
errors.push(`Unknown visual node kind: ${node.kind}`);
|
|
40
|
-
} else {
|
|
41
|
-
for (const port of definition.ports.filter((entry) => entry.direction === "input")) {
|
|
42
|
-
if (!port.optional && port.defaultValue === undefined && !hasInputOrLiteral(graph, node, port.id)) {
|
|
43
|
-
errors.push(`Missing required input on node ${node.id}: ${port.id}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
errors.push(...validateContextReferences(graph, node, options.context, options.strictReferences === true));
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
for (const edge of graph.edges) {
|
|
51
|
-
const from = nodes.get(edge.fromNode);
|
|
52
|
-
const to = nodes.get(edge.toNode);
|
|
53
|
-
if (!from) {
|
|
54
|
-
errors.push(`Missing edge source node: ${edge.fromNode}`);
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
if (!to) {
|
|
58
|
-
errors.push(`Missing edge target node: ${edge.toNode}`);
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const fromPort = from.ports.find((port) => port.id === edge.fromPort);
|
|
63
|
-
const toPort = to.ports.find((port) => port.id === edge.toPort);
|
|
64
|
-
if (!fromPort || fromPort.direction !== "output") {
|
|
65
|
-
errors.push(`Invalid source port: ${edge.fromNode}.${edge.fromPort}`);
|
|
66
|
-
}
|
|
67
|
-
if (!toPort || toPort.direction !== "input") {
|
|
68
|
-
errors.push(`Invalid target port: ${edge.toNode}.${edge.toPort}`);
|
|
69
|
-
}
|
|
70
|
-
if (fromPort && toPort && fromPort.type !== toPort.type && fromPort.type !== "any" && toPort.type !== "any") {
|
|
71
|
-
errors.push(`Port type mismatch: ${edge.fromNode}.${edge.fromPort} -> ${edge.toNode}.${edge.toPort}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (options.allowCycles !== true) {
|
|
76
|
-
errors.push(...validateAcyclic(graph));
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return errors;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function serializeGraph(graph: VisualGraph): SerializedVisualGraph {
|
|
83
|
-
const errors = validateGraph(graph);
|
|
84
|
-
if (errors.length > 0) {
|
|
85
|
-
throw new Error(errors.join("; "));
|
|
86
|
-
}
|
|
87
|
-
return {
|
|
88
|
-
nodes: graph.nodes.map((node) => ({
|
|
89
|
-
id: node.id,
|
|
90
|
-
kind: node.kind,
|
|
91
|
-
ports: node.ports.map((port) => ({ ...port })),
|
|
92
|
-
data: cloneData(node.data)
|
|
93
|
-
})),
|
|
94
|
-
edges: graph.edges.map((edge) => ({ ...edge }))
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export function deserializeGraph(serialized: SerializedVisualGraph): VisualGraph {
|
|
99
|
-
const graph: VisualGraph = {
|
|
100
|
-
nodes: serialized.nodes.map((node) => ({
|
|
101
|
-
id: node.id,
|
|
102
|
-
kind: node.kind,
|
|
103
|
-
ports: node.ports.map((port) => ({ ...port })),
|
|
104
|
-
data: cloneData(node.data)
|
|
105
|
-
})),
|
|
106
|
-
edges: serialized.edges.map((edge) => ({ ...edge }))
|
|
107
|
-
};
|
|
108
|
-
const errors = validateGraph(graph);
|
|
109
|
-
if (errors.length > 0) {
|
|
110
|
-
throw new Error(errors.join("; "));
|
|
111
|
-
}
|
|
112
|
-
return graph;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function cloneData(data: Readonly<Record<string, unknown>> | undefined): Readonly<Record<string, unknown>> | undefined {
|
|
116
|
-
if (data === undefined) return undefined;
|
|
117
|
-
return JSON.parse(JSON.stringify(data)) as Readonly<Record<string, unknown>>;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function hasInputOrLiteral(graph: VisualGraph, node: VisualNode, portId: string): boolean {
|
|
121
|
-
if (node.data && node.data[portId] !== undefined) return true;
|
|
122
|
-
return graph.edges.some((edge) => edge.toNode === node.id && edge.toPort === portId);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function validateAcyclic(graph: VisualGraph): readonly string[] {
|
|
126
|
-
const errors: string[] = [];
|
|
127
|
-
const adjacency = new Map<string, string[]>();
|
|
128
|
-
for (const node of graph.nodes) {
|
|
129
|
-
adjacency.set(node.id, []);
|
|
130
|
-
}
|
|
131
|
-
for (const edge of graph.edges) {
|
|
132
|
-
if (adjacency.has(edge.fromNode)) {
|
|
133
|
-
adjacency.get(edge.fromNode)?.push(edge.toNode);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const visiting = new Set<string>();
|
|
138
|
-
const visited = new Set<string>();
|
|
139
|
-
|
|
140
|
-
const visit = (nodeId: string, path: readonly string[]): void => {
|
|
141
|
-
if (visited.has(nodeId)) return;
|
|
142
|
-
if (visiting.has(nodeId)) {
|
|
143
|
-
errors.push(`Visual graph cycle detected: ${[...path, nodeId].join(" -> ")}`);
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
visiting.add(nodeId);
|
|
147
|
-
for (const next of adjacency.get(nodeId) ?? []) {
|
|
148
|
-
visit(next, [...path, nodeId]);
|
|
149
|
-
}
|
|
150
|
-
visiting.delete(nodeId);
|
|
151
|
-
visited.add(nodeId);
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
for (const node of graph.nodes) {
|
|
155
|
-
visit(node.id, []);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return errors;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function validateContextReferences(
|
|
162
|
-
graph: VisualGraph,
|
|
163
|
-
node: VisualNode,
|
|
164
|
-
context: VisualGraphExecutionContext | undefined,
|
|
165
|
-
strictReferences: boolean
|
|
166
|
-
): readonly string[] {
|
|
167
|
-
const errors: string[] = [];
|
|
168
|
-
const nodeId = literalString(node, "nodeId");
|
|
169
|
-
const controllerId = literalString(node, "controllerId");
|
|
170
|
-
const bodyId = literalString(node, "bodyId");
|
|
171
|
-
|
|
172
|
-
if (runtimeNodeKinds.has(node.kind)) {
|
|
173
|
-
if (strictReferences && !hasInputOrLiteral(graph, node, "nodeId")) {
|
|
174
|
-
errors.push(`Missing runtime node id on node ${node.id}`);
|
|
175
|
-
}
|
|
176
|
-
if (nodeId && context?.runtimeNodes && !collectionHas(context.runtimeNodes, nodeId)) {
|
|
177
|
-
errors.push(`Unknown runtime node id on node ${node.id}: ${nodeId}`);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (animationNodeKinds.has(node.kind)) {
|
|
182
|
-
if (strictReferences && !hasInputOrLiteral(graph, node, "controllerId")) {
|
|
183
|
-
errors.push(`Missing animation controller id on node ${node.id}`);
|
|
184
|
-
}
|
|
185
|
-
const controller = controllerId && context?.animationControllers ? collectionGet(context.animationControllers, controllerId) : undefined;
|
|
186
|
-
if (controllerId && context?.animationControllers && !controller) {
|
|
187
|
-
errors.push(`Unknown animation controller id on node ${node.id}: ${controllerId}`);
|
|
188
|
-
}
|
|
189
|
-
const clip = literalString(node, "clip");
|
|
190
|
-
if (controller && clip && controller.clips && !controller.clips.includes(clip)) {
|
|
191
|
-
errors.push(`Unknown animation clip on node ${node.id}: ${clip}`);
|
|
192
|
-
}
|
|
193
|
-
const morphTarget = literalString(node, "morphTarget");
|
|
194
|
-
if (controller && morphTarget && controller.morphTargets && !controller.morphTargets.includes(morphTarget)) {
|
|
195
|
-
errors.push(`Unknown morph target on node ${node.id}: ${morphTarget}`);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
if (physicsNodeKinds.has(node.kind)) {
|
|
200
|
-
if (strictReferences && physicsBodyRequiredKinds.has(node.kind) && !hasInputOrLiteral(graph, node, "bodyId")) {
|
|
201
|
-
errors.push(`Missing physics body id on node ${node.id}`);
|
|
202
|
-
}
|
|
203
|
-
if (bodyId && context?.physicsBodies && !collectionHas(context.physicsBodies, bodyId)) {
|
|
204
|
-
errors.push(`Unknown physics body id on node ${node.id}: ${bodyId}`);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return errors;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function literalString(node: VisualNode, key: string): string | undefined {
|
|
212
|
-
const value = node.data?.[key];
|
|
213
|
-
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function collectionHas<T extends { readonly id: string }>(collection: VisualStateCollection<T>, id: string): boolean {
|
|
217
|
-
return collectionGet(collection, id) !== undefined;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function collectionGet<T extends { readonly id: string }>(collection: VisualStateCollection<T>, id: string): T | undefined {
|
|
221
|
-
return Array.isArray(collection) ? collection.find((entry) => entry.id === id) : (collection as Readonly<Record<string, T>>)[id];
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const runtimeNodeKinds = new Set(["getNode", "setPosition", "translate", "rotate", "setVisible", "setMaterial"]);
|
|
225
|
-
const animationNodeKinds = new Set([
|
|
226
|
-
"playClip",
|
|
227
|
-
"restartClip",
|
|
228
|
-
"crossFade",
|
|
229
|
-
"setLayerWeight",
|
|
230
|
-
"onAnimationEvent",
|
|
231
|
-
"setMorphTarget",
|
|
232
|
-
"setMorphTargets",
|
|
233
|
-
"getClipTime"
|
|
234
|
-
]);
|
|
235
|
-
const physicsNodeKinds = new Set(["setVelocity", "jump", "dash", "onCollisionEnter", "onCollisionExit", "raycast", "overlap"]);
|
|
236
|
-
const physicsBodyRequiredKinds = new Set(["setVelocity", "jump", "dash", "onCollisionEnter", "onCollisionExit"]);
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
export type VisualVector3 = readonly [number, number, number] | {
|
|
2
|
-
readonly x?: number;
|
|
3
|
-
readonly y?: number;
|
|
4
|
-
readonly z?: number;
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export type VisualInputSet = readonly string[] | Readonly<Record<string, boolean>>;
|
|
8
|
-
|
|
9
|
-
export type VisualStateCollection<T extends { readonly id: string }> =
|
|
10
|
-
| readonly T[]
|
|
11
|
-
| Readonly<Record<string, T>>;
|
|
12
|
-
|
|
13
|
-
export interface VisualRuntimeNodeState {
|
|
14
|
-
readonly id: string;
|
|
15
|
-
readonly position?: VisualVector3;
|
|
16
|
-
readonly rotation?: VisualVector3;
|
|
17
|
-
readonly scale?: VisualVector3;
|
|
18
|
-
readonly visible?: boolean;
|
|
19
|
-
readonly material?: Readonly<Record<string, unknown>>;
|
|
20
|
-
readonly morphTargets?: Readonly<Record<string, number>>;
|
|
21
|
-
readonly tags?: readonly string[];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface VisualInputSnapshot {
|
|
25
|
-
readonly pressed?: VisualInputSet;
|
|
26
|
-
readonly held?: VisualInputSet;
|
|
27
|
-
readonly released?: VisualInputSet;
|
|
28
|
-
readonly buffered?: VisualInputSet;
|
|
29
|
-
readonly combos?: VisualInputSet;
|
|
30
|
-
readonly axes?: Readonly<Record<string, number>>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface VisualAnimationEvent {
|
|
34
|
-
readonly id?: string;
|
|
35
|
-
readonly type: string;
|
|
36
|
-
readonly controllerId?: string;
|
|
37
|
-
readonly clip?: string;
|
|
38
|
-
readonly time?: number;
|
|
39
|
-
readonly bone?: string;
|
|
40
|
-
readonly payload?: unknown;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface VisualAnimationControllerState {
|
|
44
|
-
readonly id: string;
|
|
45
|
-
readonly nodeId?: string;
|
|
46
|
-
readonly currentClip?: string;
|
|
47
|
-
readonly clipTime?: number;
|
|
48
|
-
readonly clips?: readonly string[];
|
|
49
|
-
readonly layers?: Readonly<Record<string, number>>;
|
|
50
|
-
readonly morphTargets?: readonly string[];
|
|
51
|
-
readonly events?: readonly VisualAnimationEvent[];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export interface VisualPhysicsBodyState {
|
|
55
|
-
readonly id: string;
|
|
56
|
-
readonly position?: VisualVector3;
|
|
57
|
-
readonly velocity?: VisualVector3;
|
|
58
|
-
readonly grounded?: boolean;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface VisualCollisionEvent {
|
|
62
|
-
readonly id?: string;
|
|
63
|
-
readonly type: "enter" | "exit";
|
|
64
|
-
readonly bodyId?: string;
|
|
65
|
-
readonly otherBodyId?: string;
|
|
66
|
-
readonly point?: VisualVector3;
|
|
67
|
-
readonly normal?: VisualVector3;
|
|
68
|
-
readonly payload?: unknown;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export interface VisualRaycastHit {
|
|
72
|
-
readonly id: string;
|
|
73
|
-
readonly hit: boolean;
|
|
74
|
-
readonly bodyId?: string;
|
|
75
|
-
readonly point?: VisualVector3;
|
|
76
|
-
readonly normal?: VisualVector3;
|
|
77
|
-
readonly distance?: number;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export interface VisualOverlapResult {
|
|
81
|
-
readonly id: string;
|
|
82
|
-
readonly bodyIds: readonly string[];
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export interface VisualCombatEvent {
|
|
86
|
-
readonly id?: string;
|
|
87
|
-
readonly type: "hit" | "blocked" | "damage" | "knockback";
|
|
88
|
-
readonly actorId?: string;
|
|
89
|
-
readonly targetId?: string;
|
|
90
|
-
readonly hitboxId?: string;
|
|
91
|
-
readonly amount?: number;
|
|
92
|
-
readonly payload?: unknown;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export interface VisualCameraState {
|
|
96
|
-
readonly id?: string;
|
|
97
|
-
readonly position?: VisualVector3;
|
|
98
|
-
readonly targetIds?: readonly string[];
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export interface VisualGraphExecutionContext {
|
|
102
|
-
readonly frame?: number;
|
|
103
|
-
readonly time?: number;
|
|
104
|
-
readonly dt?: number;
|
|
105
|
-
readonly runtimeNodes?: VisualStateCollection<VisualRuntimeNodeState>;
|
|
106
|
-
readonly input?: VisualInputSnapshot;
|
|
107
|
-
readonly animationControllers?: VisualStateCollection<VisualAnimationControllerState>;
|
|
108
|
-
readonly animationEvents?: readonly VisualAnimationEvent[];
|
|
109
|
-
readonly physicsBodies?: VisualStateCollection<VisualPhysicsBodyState>;
|
|
110
|
-
readonly collisionEvents?: readonly VisualCollisionEvent[];
|
|
111
|
-
readonly raycastHits?: VisualStateCollection<VisualRaycastHit>;
|
|
112
|
-
readonly overlaps?: VisualStateCollection<VisualOverlapResult>;
|
|
113
|
-
readonly combatEvents?: readonly VisualCombatEvent[];
|
|
114
|
-
readonly camera?: VisualCameraState;
|
|
115
|
-
readonly evidence?: Readonly<Record<string, unknown>>;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export interface VisualGraphValidationOptions {
|
|
119
|
-
readonly context?: VisualGraphExecutionContext;
|
|
120
|
-
readonly strictReferences?: boolean;
|
|
121
|
-
readonly allowCycles?: boolean;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export interface VisualGraphSideEffect {
|
|
125
|
-
readonly kind: string;
|
|
126
|
-
readonly nodeId: string;
|
|
127
|
-
readonly target?: string;
|
|
128
|
-
readonly frame?: number;
|
|
129
|
-
readonly time?: number;
|
|
130
|
-
readonly payload: unknown;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export interface VisualGraphDiagnostic {
|
|
134
|
-
readonly level: "info" | "warning" | "error";
|
|
135
|
-
readonly code: string;
|
|
136
|
-
readonly message: string;
|
|
137
|
-
readonly nodeId?: string;
|
|
138
|
-
}
|