pixifact 0.1.3
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/README.md +44 -0
- package/dist/authoring/ActionRegistry.d.ts +10 -0
- package/dist/authoring/ActionRegistry.js +26 -0
- package/dist/authoring/ComponentPalette.d.ts +16 -0
- package/dist/authoring/ComponentPalette.js +50 -0
- package/dist/authoring/DesignToken.d.ts +16 -0
- package/dist/authoring/DesignToken.js +33 -0
- package/dist/authoring/DiffModel.d.ts +10 -0
- package/dist/authoring/DiffModel.js +104 -0
- package/dist/authoring/InspectorModel.d.ts +27 -0
- package/dist/authoring/InspectorModel.js +139 -0
- package/dist/authoring/LogicGraph.d.ts +66 -0
- package/dist/authoring/LogicGraph.js +184 -0
- package/dist/authoring/OverrideJournal.d.ts +18 -0
- package/dist/authoring/OverrideJournal.js +23 -0
- package/dist/authoring/PreferenceMemory.d.ts +21 -0
- package/dist/authoring/PreferenceMemory.js +39 -0
- package/dist/authoring/ProjectConfig.d.ts +20 -0
- package/dist/authoring/ProjectConfig.js +78 -0
- package/dist/authoring/RuntimePreview.d.ts +11 -0
- package/dist/authoring/RuntimePreview.js +25 -0
- package/dist/authoring/SceneDocument.d.ts +74 -0
- package/dist/authoring/SceneDocument.js +332 -0
- package/dist/authoring/SceneProjectState.d.ts +20 -0
- package/dist/authoring/SceneProjectState.js +8 -0
- package/dist/authoring/SceneSelection.d.ts +11 -0
- package/dist/authoring/SceneSelection.js +1 -0
- package/dist/authoring/index.d.ts +13 -0
- package/dist/authoring/index.js +13 -0
- package/dist/commands/Command.d.ts +63 -0
- package/dist/commands/Command.js +1 -0
- package/dist/commands/CommandStack.d.ts +14 -0
- package/dist/commands/CommandStack.js +45 -0
- package/dist/commands/applyCommand.d.ts +23 -0
- package/dist/commands/applyCommand.js +316 -0
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.js +4 -0
- package/dist/commands/utils.d.ts +17 -0
- package/dist/commands/utils.js +77 -0
- package/dist/commands/validateCommand.d.ts +12 -0
- package/dist/commands/validateCommand.js +285 -0
- package/dist/compiler/commands/index.d.ts +109 -0
- package/dist/compiler/commands/index.js +492 -0
- package/dist/compiler/compileScenes.d.ts +11 -0
- package/dist/compiler/compileScenes.js +220 -0
- package/dist/compiler/decorators.d.ts +6 -0
- package/dist/compiler/decorators.js +79 -0
- package/dist/compiler/eventRuntime.d.ts +8 -0
- package/dist/compiler/eventRuntime.js +29 -0
- package/dist/compiler/index.d.ts +14 -0
- package/dist/compiler/index.js +14 -0
- package/dist/compiler/pixiNodeSchema.d.ts +39 -0
- package/dist/compiler/pixiNodeSchema.js +267 -0
- package/dist/compiler/sceneAssetPair.d.ts +11 -0
- package/dist/compiler/sceneAssetPair.js +92 -0
- package/dist/compiler/scenePartValidation.d.ts +6 -0
- package/dist/compiler/scenePartValidation.js +24 -0
- package/dist/compiler/sceneRuntime.d.ts +13 -0
- package/dist/compiler/sceneRuntime.js +22 -0
- package/dist/compiler/sceneValidation.d.ts +48 -0
- package/dist/compiler/sceneValidation.js +383 -0
- package/dist/compiler/scriptInterfaceExtractor.d.ts +6 -0
- package/dist/compiler/scriptInterfaceExtractor.js +258 -0
- package/dist/compiler/slotRuntime.d.ts +3 -0
- package/dist/compiler/slotRuntime.js +17 -0
- package/dist/compiler/spec.d.ts +95 -0
- package/dist/compiler/spec.js +1 -0
- package/dist/compiler/templateParser.d.ts +2 -0
- package/dist/compiler/templateParser.js +302 -0
- package/dist/compiler/templateSerializer.d.ts +2 -0
- package/dist/compiler/templateSerializer.js +101 -0
- package/dist/compiler/typescriptCompiler.d.ts +2 -0
- package/dist/compiler/typescriptCompiler.js +494 -0
- package/dist/compiler-node/index.d.ts +2 -0
- package/dist/compiler-node/index.js +2 -0
- package/dist/compiler-node/vite.d.ts +8 -0
- package/dist/compiler-node/vite.js +21 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/nodes/Input.d.ts +91 -0
- package/dist/nodes/Input.js +352 -0
- package/dist/nodes/Textarea.d.ts +10 -0
- package/dist/nodes/Textarea.js +38 -0
- package/dist/nodes/components/Button.d.ts +8 -0
- package/dist/nodes/components/Button.js +45 -0
- package/dist/nodes/components/InputField.d.ts +12 -0
- package/dist/nodes/components/InputField.js +53 -0
- package/dist/nodes/components/ProgressBar.d.ts +14 -0
- package/dist/nodes/components/ProgressBar.js +66 -0
- package/dist/nodes/components/ScrollRect.d.ts +23 -0
- package/dist/nodes/components/ScrollRect.js +108 -0
- package/dist/nodes/components/Selectable.d.ts +32 -0
- package/dist/nodes/components/Selectable.js +153 -0
- package/dist/nodes/components/index.d.ts +5 -0
- package/dist/nodes/components/index.js +5 -0
- package/dist/nodes/graphics/Graphic.d.ts +14 -0
- package/dist/nodes/graphics/Graphic.js +47 -0
- package/dist/nodes/graphics/ImageGraphic.d.ts +9 -0
- package/dist/nodes/graphics/ImageGraphic.js +42 -0
- package/dist/nodes/graphics/RoundedRectGraphic.d.ts +13 -0
- package/dist/nodes/graphics/RoundedRectGraphic.js +65 -0
- package/dist/nodes/graphics/TextGraphic.d.ts +13 -0
- package/dist/nodes/graphics/TextGraphic.js +70 -0
- package/dist/nodes/graphics/index.d.ts +4 -0
- package/dist/nodes/graphics/index.js +4 -0
- package/dist/nodes/index.d.ts +3 -0
- package/dist/nodes/index.js +3 -0
- package/dist/runtime/Application.d.ts +15 -0
- package/dist/runtime/Application.js +67 -0
- package/dist/runtime/GameObject.d.ts +100 -0
- package/dist/runtime/GameObject.js +297 -0
- package/dist/runtime/GameObjectEvent.d.ts +52 -0
- package/dist/runtime/GameObjectEvent.js +38 -0
- package/dist/runtime/Transform.d.ts +32 -0
- package/dist/runtime/Transform.js +157 -0
- package/dist/runtime/component/Component.d.ts +13 -0
- package/dist/runtime/component/Component.js +13 -0
- package/dist/runtime/component/ComponentRegistry.d.ts +49 -0
- package/dist/runtime/component/ComponentRegistry.js +25 -0
- package/dist/runtime/component/Flex.d.ts +6 -0
- package/dist/runtime/component/Flex.js +15 -0
- package/dist/runtime/component/FlexGroup.d.ts +26 -0
- package/dist/runtime/component/FlexGroup.js +136 -0
- package/dist/runtime/component/GridLayout.d.ts +47 -0
- package/dist/runtime/component/GridLayout.js +129 -0
- package/dist/runtime/component/Layout.d.ts +104 -0
- package/dist/runtime/component/Layout.js +248 -0
- package/dist/runtime/component/decorators.d.ts +4 -0
- package/dist/runtime/component/decorators.js +52 -0
- package/dist/runtime/component/index.d.ts +7 -0
- package/dist/runtime/component/index.js +7 -0
- package/dist/runtime/graphics/index.d.ts +11 -0
- package/dist/runtime/graphics/index.js +29 -0
- package/dist/runtime/group/index.d.ts +39 -0
- package/dist/runtime/group/index.js +102 -0
- package/dist/runtime/image/Image.d.ts +19 -0
- package/dist/runtime/image/Image.js +60 -0
- package/dist/runtime/image/NineSliceImage.d.ts +23 -0
- package/dist/runtime/image/NineSliceImage.js +64 -0
- package/dist/runtime/image/index.d.ts +2 -0
- package/dist/runtime/image/index.js +2 -0
- package/dist/runtime/index.d.ts +9 -0
- package/dist/runtime/index.js +9 -0
- package/dist/runtime/label/Label.d.ts +11 -0
- package/dist/runtime/label/Label.js +26 -0
- package/dist/runtime/label/LabelStyle.d.ts +3 -0
- package/dist/runtime/label/LabelStyle.js +3 -0
- package/dist/runtime/label/index.d.ts +2 -0
- package/dist/runtime/label/index.js +2 -0
- package/dist/runtime/utils/index.d.ts +1 -0
- package/dist/runtime/utils/index.js +1 -0
- package/dist/runtime/utils/onlyOnceQueueMicrotask.d.ts +1 -0
- package/dist/runtime/utils/onlyOnceQueueMicrotask.js +12 -0
- package/dist/runtime/utils/setProps.d.ts +10 -0
- package/dist/runtime/utils/setProps.js +17 -0
- package/dist/scene/dsl.d.ts +25 -0
- package/dist/scene/dsl.js +112 -0
- package/dist/scene/index.d.ts +5 -0
- package/dist/scene/index.js +5 -0
- package/dist/scene/instantiate.d.ts +8 -0
- package/dist/scene/instantiate.js +208 -0
- package/dist/scene/nodesDsl.d.ts +42 -0
- package/dist/scene/nodesDsl.js +169 -0
- package/dist/scene/spec.d.ts +100 -0
- package/dist/scene/spec.js +1 -0
- package/dist/scene/templates.d.ts +21 -0
- package/dist/scene/templates.js +239 -0
- package/package.json +90 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { ComponentRegistry } from "../runtime/index.js";
|
|
2
|
+
import { findComponent, findNode, hasDuplicateComponentId, hasDuplicateNodeId, isDescendant } from "./utils.js";
|
|
3
|
+
import { actionExists } from "../authoring/ActionRegistry.js";
|
|
4
|
+
function ok() {
|
|
5
|
+
return { ok: true };
|
|
6
|
+
}
|
|
7
|
+
function fail(error) {
|
|
8
|
+
return { ok: false, error };
|
|
9
|
+
}
|
|
10
|
+
function canContainChildNode(node, root) {
|
|
11
|
+
return node === root || node.kind === 'container';
|
|
12
|
+
}
|
|
13
|
+
function validateChildParent(parent, root) {
|
|
14
|
+
return canContainChildNode(parent, root)
|
|
15
|
+
? ok()
|
|
16
|
+
: fail('Only container nodes can contain child nodes.');
|
|
17
|
+
}
|
|
18
|
+
function validateNodeSpec(node) {
|
|
19
|
+
if (!['container', 'image', 'text', 'input', 'shape'].includes(node.kind)) {
|
|
20
|
+
return fail('Node kind must be one of: container, image, text, input, shape.');
|
|
21
|
+
}
|
|
22
|
+
if (node.kind !== 'container' && Array.isArray(node.children) && node.children.length > 0) {
|
|
23
|
+
return fail('Only container nodes can declare children.');
|
|
24
|
+
}
|
|
25
|
+
if (node.kind === 'container') {
|
|
26
|
+
for (const child of node.children ?? []) {
|
|
27
|
+
const result = validateNodeSpec(child);
|
|
28
|
+
if (!result.ok) {
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return ok();
|
|
34
|
+
}
|
|
35
|
+
function validateValue(prop, value, context = {}) {
|
|
36
|
+
if (value === undefined) {
|
|
37
|
+
return ok();
|
|
38
|
+
}
|
|
39
|
+
switch (prop.type) {
|
|
40
|
+
case 'number':
|
|
41
|
+
case 'color':
|
|
42
|
+
return typeof value === 'number' ? ok() : fail(`Prop "${prop.key}" expects a number.`);
|
|
43
|
+
case 'string':
|
|
44
|
+
return typeof value === 'string' ? ok() : fail(`Prop "${prop.key}" expects a string.`);
|
|
45
|
+
case 'event':
|
|
46
|
+
if (typeof value !== 'string') {
|
|
47
|
+
return fail(`Prop "${prop.key}" expects an action key string.`);
|
|
48
|
+
}
|
|
49
|
+
if (context.actions && !actionExists(context.actions, value)) {
|
|
50
|
+
return fail(`Action "${value}" is not declared in the project action registry.`);
|
|
51
|
+
}
|
|
52
|
+
return ok();
|
|
53
|
+
case 'assetRef':
|
|
54
|
+
case 'nodeRef':
|
|
55
|
+
case 'componentRef':
|
|
56
|
+
return typeof value === 'string' || (typeof value === 'object' && value !== null)
|
|
57
|
+
? ok()
|
|
58
|
+
: fail(`Prop "${prop.key}" expects a reference or string value.`);
|
|
59
|
+
case 'boolean':
|
|
60
|
+
return typeof value === 'boolean' ? ok() : fail(`Prop "${prop.key}" expects a boolean.`);
|
|
61
|
+
case 'enum':
|
|
62
|
+
return prop.options?.includes(value)
|
|
63
|
+
? ok()
|
|
64
|
+
: fail(`Prop "${prop.key}" expects one of: ${(prop.options ?? []).join(', ')}.`);
|
|
65
|
+
case 'vec2':
|
|
66
|
+
case 'rect':
|
|
67
|
+
return typeof value === 'object' && value !== null ? ok() : fail(`Prop "${prop.key}" expects an object.`);
|
|
68
|
+
default:
|
|
69
|
+
return ok();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function displayProp(type, key, options) {
|
|
73
|
+
return {
|
|
74
|
+
key,
|
|
75
|
+
type,
|
|
76
|
+
options,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const nodeDataProps = {
|
|
80
|
+
image: [
|
|
81
|
+
displayProp('enum', 'mode', ['sprite', 'nineSlice']),
|
|
82
|
+
displayProp('assetRef', 'src'),
|
|
83
|
+
displayProp('color', 'tint'),
|
|
84
|
+
displayProp('number', 'leftWidth'),
|
|
85
|
+
displayProp('number', 'rightWidth'),
|
|
86
|
+
displayProp('number', 'topHeight'),
|
|
87
|
+
displayProp('number', 'bottomHeight'),
|
|
88
|
+
],
|
|
89
|
+
text: [
|
|
90
|
+
displayProp('string', 'value'),
|
|
91
|
+
displayProp('color', 'color'),
|
|
92
|
+
displayProp('number', 'fontSize'),
|
|
93
|
+
displayProp('string', 'fontFamily'),
|
|
94
|
+
displayProp('enum', 'fontWeight', ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900']),
|
|
95
|
+
displayProp('boolean', 'center'),
|
|
96
|
+
],
|
|
97
|
+
input: [
|
|
98
|
+
displayProp('string', 'value'),
|
|
99
|
+
displayProp('color', 'backgroundColor'),
|
|
100
|
+
displayProp('color', 'borderColor'),
|
|
101
|
+
displayProp('number', 'borderSize'),
|
|
102
|
+
displayProp('string', 'textColor'),
|
|
103
|
+
displayProp('number', 'fontSize'),
|
|
104
|
+
displayProp('string', 'fontFamily'),
|
|
105
|
+
displayProp('number', 'paddingLeft'),
|
|
106
|
+
displayProp('number', 'paddingRight'),
|
|
107
|
+
displayProp('number', 'paddingTop'),
|
|
108
|
+
displayProp('number', 'paddingBottom'),
|
|
109
|
+
],
|
|
110
|
+
shape: [
|
|
111
|
+
displayProp('enum', 'type', ['rect', 'roundedRect']),
|
|
112
|
+
displayProp('color', 'color'),
|
|
113
|
+
displayProp('number', 'fillAlpha'),
|
|
114
|
+
displayProp('number', 'radius'),
|
|
115
|
+
displayProp('color', 'strokeColor'),
|
|
116
|
+
displayProp('number', 'strokeWidth'),
|
|
117
|
+
displayProp('number', 'strokeAlpha'),
|
|
118
|
+
],
|
|
119
|
+
};
|
|
120
|
+
function validateSetNodeData(scene, command) {
|
|
121
|
+
const locatedNode = findNode(scene, command.node);
|
|
122
|
+
if (!locatedNode) {
|
|
123
|
+
return fail(`Node "${command.node}" was not found.`);
|
|
124
|
+
}
|
|
125
|
+
if (locatedNode.node.kind !== command.field) {
|
|
126
|
+
return fail(`Node "${command.node}" is ${locatedNode.node.kind}, not ${command.field}.`);
|
|
127
|
+
}
|
|
128
|
+
const prop = nodeDataProps[command.field].find((candidate) => candidate.key === command.prop);
|
|
129
|
+
if (!prop) {
|
|
130
|
+
return fail(`Node data prop "${command.prop}" does not exist on ${command.field}.`);
|
|
131
|
+
}
|
|
132
|
+
return validateValue(prop, command.value);
|
|
133
|
+
}
|
|
134
|
+
function validateComponentSpec(component, context = {}) {
|
|
135
|
+
const schema = ComponentRegistry.get(component.type);
|
|
136
|
+
if (!schema) {
|
|
137
|
+
return fail(`Unknown component type "${component.type}".`);
|
|
138
|
+
}
|
|
139
|
+
for (const [key, value] of Object.entries(component.props ?? {})) {
|
|
140
|
+
const prop = schema.props.find((candidate) => candidate.key === key);
|
|
141
|
+
if (!prop) {
|
|
142
|
+
return fail(`Prop "${key}" does not exist on ${component.type}.`);
|
|
143
|
+
}
|
|
144
|
+
const result = validateValue(prop, value, context);
|
|
145
|
+
if (!result.ok) {
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return ok();
|
|
150
|
+
}
|
|
151
|
+
function validateSetComponentProp(scene, command, context = {}) {
|
|
152
|
+
const locatedNode = findNode(scene, command.node);
|
|
153
|
+
if (!locatedNode) {
|
|
154
|
+
return fail(`Node "${command.node}" was not found.`);
|
|
155
|
+
}
|
|
156
|
+
const locatedComponent = findComponent(locatedNode.node, command.component);
|
|
157
|
+
if (!locatedComponent) {
|
|
158
|
+
return fail(`Component "${command.component}" was not found on node "${command.node}".`);
|
|
159
|
+
}
|
|
160
|
+
const schema = ComponentRegistry.get(locatedComponent.component.type);
|
|
161
|
+
if (!schema) {
|
|
162
|
+
return fail(`Unknown component type "${locatedComponent.component.type}".`);
|
|
163
|
+
}
|
|
164
|
+
const prop = schema.props.find((candidate) => candidate.key === command.prop);
|
|
165
|
+
if (!prop) {
|
|
166
|
+
return fail(`Prop "${command.prop}" does not exist on ${schema.type}.`);
|
|
167
|
+
}
|
|
168
|
+
return validateValue(prop, command.value, context);
|
|
169
|
+
}
|
|
170
|
+
function validateAddComponent(scene, command, context = {}) {
|
|
171
|
+
const locatedNode = findNode(scene, command.node);
|
|
172
|
+
if (!locatedNode) {
|
|
173
|
+
return fail(`Node "${command.node}" was not found.`);
|
|
174
|
+
}
|
|
175
|
+
const result = validateComponentSpec(command.component, context);
|
|
176
|
+
if (!result.ok) {
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
const schema = ComponentRegistry.get(command.component.type);
|
|
180
|
+
if (schema?.disallowMultiple && (locatedNode.node.components ?? []).some((component) => component.type === command.component.type)) {
|
|
181
|
+
return fail(`Component "${command.component.type}" cannot be added more than once.`);
|
|
182
|
+
}
|
|
183
|
+
if (command.component.id && hasDuplicateComponentId(locatedNode.node, command.component.id)) {
|
|
184
|
+
return fail(`Component id "${command.component.id}" already exists on node "${command.node}".`);
|
|
185
|
+
}
|
|
186
|
+
return ok();
|
|
187
|
+
}
|
|
188
|
+
function validateSetNodeProp(scene, command) {
|
|
189
|
+
const locatedNode = findNode(scene, command.node);
|
|
190
|
+
if (!locatedNode) {
|
|
191
|
+
return fail(`Node "${command.node}" was not found.`);
|
|
192
|
+
}
|
|
193
|
+
if (command.value !== undefined && typeof command.value !== 'string') {
|
|
194
|
+
return fail(`Node prop "${command.prop}" expects a string.`);
|
|
195
|
+
}
|
|
196
|
+
if (command.prop === 'id' && command.value) {
|
|
197
|
+
const duplicate = findNode(scene, command.value);
|
|
198
|
+
if (duplicate && duplicate.node !== locatedNode.node) {
|
|
199
|
+
return fail(`Node id "${command.value}" already exists.`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return ok();
|
|
203
|
+
}
|
|
204
|
+
function validateReparentNode(scene, command) {
|
|
205
|
+
const locatedNode = findNode(scene, command.node);
|
|
206
|
+
if (!locatedNode) {
|
|
207
|
+
return fail(`Node "${command.node}" was not found.`);
|
|
208
|
+
}
|
|
209
|
+
if (locatedNode.node === scene.root) {
|
|
210
|
+
return fail('Root node cannot be reparented.');
|
|
211
|
+
}
|
|
212
|
+
const parent = command.parent ? findNode(scene, command.parent) : undefined;
|
|
213
|
+
if (command.parent && !parent) {
|
|
214
|
+
return fail(`Parent node "${command.parent}" was not found.`);
|
|
215
|
+
}
|
|
216
|
+
if (parent && (parent.node === locatedNode.node || isDescendant(parent.node, locatedNode.node))) {
|
|
217
|
+
return fail(`Node "${command.node}" cannot be reparented under itself or its descendant.`);
|
|
218
|
+
}
|
|
219
|
+
return validateChildParent(parent?.node ?? scene.root, scene.root);
|
|
220
|
+
}
|
|
221
|
+
function validateReorderNode(scene, command) {
|
|
222
|
+
const locatedNode = findNode(scene, command.node);
|
|
223
|
+
if (!locatedNode) {
|
|
224
|
+
return fail(`Node "${command.node}" was not found.`);
|
|
225
|
+
}
|
|
226
|
+
if (!locatedNode.parent) {
|
|
227
|
+
return fail('Root node cannot be reordered.');
|
|
228
|
+
}
|
|
229
|
+
if (!Number.isInteger(command.index) || command.index < 0) {
|
|
230
|
+
return fail('Reorder index must be a non-negative integer.');
|
|
231
|
+
}
|
|
232
|
+
return ok();
|
|
233
|
+
}
|
|
234
|
+
export function validateCommand(scene, command, context = {}) {
|
|
235
|
+
switch (command.op) {
|
|
236
|
+
case 'setNodeProp':
|
|
237
|
+
return validateSetNodeProp(scene, command);
|
|
238
|
+
case 'setTransform':
|
|
239
|
+
return findNode(scene, command.node) ? ok() : fail(`Node "${command.node}" was not found.`);
|
|
240
|
+
case 'setNodeData':
|
|
241
|
+
return validateSetNodeData(scene, command);
|
|
242
|
+
case 'setComponentProp':
|
|
243
|
+
return validateSetComponentProp(scene, command, context);
|
|
244
|
+
case 'addComponent':
|
|
245
|
+
return validateAddComponent(scene, command, context);
|
|
246
|
+
case 'removeComponent': {
|
|
247
|
+
const locatedNode = findNode(scene, command.node);
|
|
248
|
+
if (!locatedNode) {
|
|
249
|
+
return fail(`Node "${command.node}" was not found.`);
|
|
250
|
+
}
|
|
251
|
+
return findComponent(locatedNode.node, command.component)
|
|
252
|
+
? ok()
|
|
253
|
+
: fail(`Component "${command.component}" was not found on node "${command.node}".`);
|
|
254
|
+
}
|
|
255
|
+
case 'createNode':
|
|
256
|
+
const parent = command.parent ? findNode(scene, command.parent) : undefined;
|
|
257
|
+
if (command.parent && !parent) {
|
|
258
|
+
return fail(`Parent node "${command.parent}" was not found.`);
|
|
259
|
+
}
|
|
260
|
+
{
|
|
261
|
+
const result = validateNodeSpec(command.node);
|
|
262
|
+
if (!result.ok) {
|
|
263
|
+
return result;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (command.node.id && hasDuplicateNodeId(scene, command.node.id)) {
|
|
267
|
+
return fail(`Node id "${command.node.id}" already exists.`);
|
|
268
|
+
}
|
|
269
|
+
return validateChildParent(parent?.node ?? scene.root, scene.root);
|
|
270
|
+
case 'deleteNode':
|
|
271
|
+
if (scene.root.id === command.node || scene.root.key === command.node || scene.root.name === command.node) {
|
|
272
|
+
return fail('Root node cannot be deleted.');
|
|
273
|
+
}
|
|
274
|
+
return findNode(scene, command.node) ? ok() : fail(`Node "${command.node}" was not found.`);
|
|
275
|
+
case 'reparentNode':
|
|
276
|
+
return validateReparentNode(scene, command);
|
|
277
|
+
case 'reorderNode':
|
|
278
|
+
return validateReorderNode(scene, command);
|
|
279
|
+
case 'batch':
|
|
280
|
+
return Array.isArray(command.commands) ? ok() : fail('Batch command expects a commands array.');
|
|
281
|
+
default:
|
|
282
|
+
return fail('Unknown command.');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
export const validateSceneCommand = validateCommand;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { SceneTemplate, SceneTemplateInterface, SceneTemplateNode, SceneTemplateValue } from '../spec.js';
|
|
2
|
+
export type CompilerSceneSelection = {
|
|
3
|
+
type: 'scene';
|
|
4
|
+
} | {
|
|
5
|
+
type: 'node';
|
|
6
|
+
node: string;
|
|
7
|
+
};
|
|
8
|
+
export type CompilerSceneCommand = {
|
|
9
|
+
op: 'setSceneName';
|
|
10
|
+
value: string;
|
|
11
|
+
} | {
|
|
12
|
+
op: 'setSceneProp';
|
|
13
|
+
prop: string;
|
|
14
|
+
value?: SceneTemplateValue;
|
|
15
|
+
} | {
|
|
16
|
+
op: 'setNodeId';
|
|
17
|
+
node: string;
|
|
18
|
+
value?: string;
|
|
19
|
+
} | {
|
|
20
|
+
op: 'setNodeProp';
|
|
21
|
+
node: string;
|
|
22
|
+
prop: string;
|
|
23
|
+
value?: SceneTemplateValue;
|
|
24
|
+
} | {
|
|
25
|
+
op: 'setNodeEvent';
|
|
26
|
+
node: string;
|
|
27
|
+
event: string;
|
|
28
|
+
value?: string;
|
|
29
|
+
} | {
|
|
30
|
+
op: 'renameSlotOutlet';
|
|
31
|
+
node: string;
|
|
32
|
+
name: string;
|
|
33
|
+
} | {
|
|
34
|
+
op: 'insertNode';
|
|
35
|
+
parent: string;
|
|
36
|
+
index?: number;
|
|
37
|
+
node: SceneTemplateNode;
|
|
38
|
+
} | {
|
|
39
|
+
op: 'deleteNode';
|
|
40
|
+
node: string;
|
|
41
|
+
} | {
|
|
42
|
+
op: 'moveNode';
|
|
43
|
+
node: string;
|
|
44
|
+
parent: string;
|
|
45
|
+
index: number;
|
|
46
|
+
} | {
|
|
47
|
+
op: 'batch';
|
|
48
|
+
commands: CompilerSceneCommand[];
|
|
49
|
+
};
|
|
50
|
+
export type CompilerSceneCommandResult = {
|
|
51
|
+
ok: true;
|
|
52
|
+
command: CompilerSceneCommand;
|
|
53
|
+
inverse: CompilerSceneCommand;
|
|
54
|
+
selection?: CompilerSceneSelection;
|
|
55
|
+
} | {
|
|
56
|
+
ok: false;
|
|
57
|
+
command: CompilerSceneCommand;
|
|
58
|
+
error: string;
|
|
59
|
+
};
|
|
60
|
+
export interface CompilerSceneCommandContext {
|
|
61
|
+
sceneInterfaces?: Record<string, SceneTemplateInterface>;
|
|
62
|
+
}
|
|
63
|
+
export interface CompilerSceneCommandStackOptions {
|
|
64
|
+
label?: string;
|
|
65
|
+
mergeKey?: string;
|
|
66
|
+
}
|
|
67
|
+
export declare function compilerSceneNodeLocator(node: SceneTemplateNode, path?: string): string;
|
|
68
|
+
export declare function applyCompilerSceneCommand(template: SceneTemplate, command: CompilerSceneCommand, context?: CompilerSceneCommandContext): CompilerSceneCommandResult;
|
|
69
|
+
export declare class CompilerSceneCommandStack {
|
|
70
|
+
private undoStack;
|
|
71
|
+
private redoStack;
|
|
72
|
+
private currentRevision;
|
|
73
|
+
private savedRevision;
|
|
74
|
+
get canUndo(): boolean;
|
|
75
|
+
get canRedo(): boolean;
|
|
76
|
+
get dirty(): boolean;
|
|
77
|
+
execute(template: SceneTemplate, command: CompilerSceneCommand, options?: CompilerSceneCommandStackOptions, context?: CompilerSceneCommandContext): {
|
|
78
|
+
ok: true;
|
|
79
|
+
command: CompilerSceneCommand;
|
|
80
|
+
inverse: CompilerSceneCommand;
|
|
81
|
+
selection?: CompilerSceneSelection;
|
|
82
|
+
} | {
|
|
83
|
+
ok: false;
|
|
84
|
+
command: CompilerSceneCommand;
|
|
85
|
+
error: string;
|
|
86
|
+
};
|
|
87
|
+
undo(template: SceneTemplate, context?: CompilerSceneCommandContext): {
|
|
88
|
+
ok: true;
|
|
89
|
+
command: CompilerSceneCommand;
|
|
90
|
+
inverse: CompilerSceneCommand;
|
|
91
|
+
selection?: CompilerSceneSelection;
|
|
92
|
+
} | {
|
|
93
|
+
ok: false;
|
|
94
|
+
command: CompilerSceneCommand;
|
|
95
|
+
error: string;
|
|
96
|
+
} | undefined;
|
|
97
|
+
redo(template: SceneTemplate, context?: CompilerSceneCommandContext): {
|
|
98
|
+
ok: true;
|
|
99
|
+
command: CompilerSceneCommand;
|
|
100
|
+
inverse: CompilerSceneCommand;
|
|
101
|
+
selection?: CompilerSceneSelection;
|
|
102
|
+
} | {
|
|
103
|
+
ok: false;
|
|
104
|
+
command: CompilerSceneCommand;
|
|
105
|
+
error: string;
|
|
106
|
+
} | undefined;
|
|
107
|
+
markSaved(): void;
|
|
108
|
+
clear(): void;
|
|
109
|
+
}
|