@vgai/engine 0.5.15 → 0.5.16
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/dist/adapter/adapter-module.d.ts +228 -17
- package/dist/adapter/adapter-module.d.ts.map +1 -1
- package/dist/adapter/adapter-module.js +224 -42
- package/dist/adapter/authoring-seam-contract.d.ts +530 -0
- package/dist/adapter/authoring-seam-contract.d.ts.map +1 -0
- package/dist/adapter/authoring-seam-contract.js +162 -0
- package/dist/adapter/authoring.d.ts +237 -50
- package/dist/adapter/authoring.d.ts.map +1 -1
- package/dist/adapter/authoring.js +2 -1
- package/dist/adapter/entrypoint-selection-source.d.ts +35 -0
- package/dist/adapter/entrypoint-selection-source.d.ts.map +1 -0
- package/dist/adapter/entrypoint-selection-source.js +151 -0
- package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts +7 -1
- package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts.map +1 -1
- package/dist/adapter/finders/scenes-from-entrypoint-selection.js +142 -21
- package/dist/adapter/first-party-systems.d.ts +13 -3
- package/dist/adapter/first-party-systems.d.ts.map +1 -1
- package/dist/adapter/first-party-systems.js +10 -3
- package/dist/adapter/index.d.ts +7 -2
- package/dist/adapter/index.d.ts.map +1 -1
- package/dist/adapter/index.js +4 -0
- package/dist/adapter/ingest/contract-system-adapters.d.ts +1 -1
- package/dist/adapter/ingest/contract-system-adapters.d.ts.map +1 -1
- package/dist/adapter/ingest/contract-system-adapters.js +13 -25
- package/dist/adapter/ingest/game-contract-seams.d.ts +214 -0
- package/dist/adapter/ingest/game-contract-seams.d.ts.map +1 -0
- package/dist/adapter/ingest/game-contract-seams.js +62 -0
- package/dist/adapter/ingest/game-contract.d.ts +5 -3
- package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
- package/dist/adapter/ingest/game-contract.js +4 -1
- package/dist/adapter/ingest/merge-debug-adapters.d.ts +52 -0
- package/dist/adapter/ingest/merge-debug-adapters.d.ts.map +1 -0
- package/dist/adapter/ingest/merge-debug-adapters.js +141 -0
- package/dist/adapter/ingest/observation-debug-adapter.d.ts +56 -0
- package/dist/adapter/ingest/observation-debug-adapter.d.ts.map +1 -0
- package/dist/adapter/ingest/observation-debug-adapter.js +131 -0
- package/dist/adapter/ingest/scene-capture.d.ts +38 -13
- package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
- package/dist/adapter/ingest/scene-capture.js +101 -24
- package/dist/adapter/ingest/visible-capture-window.d.ts +22 -5
- package/dist/adapter/ingest/visible-capture-window.d.ts.map +1 -1
- package/dist/adapter/ingest/visible-capture-window.js +46 -7
- package/dist/adapter/native-debug-module.d.ts +43 -0
- package/dist/adapter/native-debug-module.d.ts.map +1 -0
- package/dist/adapter/native-debug-module.js +230 -0
- package/dist/adapter/object3d-authoring-subject.d.ts +32 -0
- package/dist/adapter/object3d-authoring-subject.d.ts.map +1 -0
- package/dist/adapter/object3d-authoring-subject.js +25 -0
- package/dist/adapter/root-adapter.d.ts +21 -56
- package/dist/adapter/root-adapter.d.ts.map +1 -1
- package/dist/adapter/root-adapter.js +4 -20
- package/dist/adapter/root-seam-contract.d.ts +124 -0
- package/dist/adapter/root-seam-contract.d.ts.map +1 -0
- package/dist/adapter/root-seam-contract.js +36 -0
- package/dist/adapter/seam-evidence.d.ts +118 -0
- package/dist/adapter/seam-evidence.d.ts.map +1 -0
- package/dist/adapter/seam-evidence.js +231 -0
- package/dist/adapter/setup-three-root-adapter.d.ts +2 -3
- package/dist/adapter/setup-three-root-adapter.d.ts.map +1 -1
- package/dist/adapter/setup-three-root-adapter.js +2 -3
- package/dist/adapter/system-adapter.d.ts +6 -1
- package/dist/adapter/system-adapter.d.ts.map +1 -1
- package/dist/adapter/system-seam-contract.d.ts +354 -0
- package/dist/adapter/system-seam-contract.d.ts.map +1 -0
- package/dist/adapter/system-seam-contract.js +95 -0
- package/dist/animation/xstate-animation-binding.d.ts +6 -0
- package/dist/animation/xstate-animation-binding.d.ts.map +1 -1
- package/dist/animation/xstate-animation-binding.js +142 -4
- package/dist/asset-formats/collider.d.ts +1 -1
- package/dist/asset-formats/mesh.d.ts +2 -2
- package/dist/asset-formats/particles.d.ts +1 -1
- package/dist/canvas-react/engine-bridge.d.ts +6 -6
- package/dist/canvas-react/engine-bridge.d.ts.map +1 -1
- package/dist/canvas-react/engine-bridge.js +2 -2
- package/dist/canvas-react/index.d.ts +2 -2
- package/dist/canvas-react/index.d.ts.map +1 -1
- package/dist/canvas-react/index.js +1 -1
- package/dist/canvas-react/pixi-react-adapter.d.ts +15 -9
- package/dist/canvas-react/pixi-react-adapter.d.ts.map +1 -1
- package/dist/canvas-react/pixi-react-adapter.js +43 -29
- package/dist/canvas-react/pixi-react-root-factory.d.ts.map +1 -1
- package/dist/canvas-react/pixi-react-root-factory.js +4 -0
- package/dist/canvas-react/world-context.d.ts +22 -12
- package/dist/canvas-react/world-context.d.ts.map +1 -1
- package/dist/canvas-react/world-context.js +12 -51
- package/dist/ecs/user-data.d.ts +5 -0
- package/dist/ecs/user-data.d.ts.map +1 -1
- package/dist/ecs/user-data.js +3 -0
- package/dist/input/input-manager.d.ts +49 -0
- package/dist/input/input-manager.d.ts.map +1 -1
- package/dist/input/input-manager.js +127 -0
- package/dist/manifest/schema.d.ts +9 -9
- package/dist/pixi/authoring.d.ts.map +1 -1
- package/dist/pixi/authoring.js +220 -1
- package/dist/pixi/ingest.d.ts +2 -1
- package/dist/pixi/ingest.d.ts.map +1 -1
- package/dist/pixi/ingest.js +4 -2
- package/dist/pixi/scene-capture.d.ts +9 -1
- package/dist/pixi/scene-capture.d.ts.map +1 -1
- package/dist/pixi/scene-capture.js +9 -6
- package/dist/render/particles-factory.d.ts +13 -6
- package/dist/render/particles-factory.d.ts.map +1 -1
- package/dist/render/particles-factory.js +6 -3
- package/dist/runtime/create-runtime.d.ts +23 -46
- package/dist/runtime/create-runtime.d.ts.map +1 -1
- package/dist/runtime/create-runtime.js +22 -67
- package/dist/runtime/game.d.ts +29 -71
- package/dist/runtime/game.d.ts.map +1 -1
- package/dist/runtime/game.js +15 -54
- package/dist/runtime/mount-game.d.ts.map +1 -1
- package/dist/runtime/mount-game.js +12 -1
- package/dist/runtime/mount-manifest.d.ts.map +1 -1
- package/dist/runtime/mount-manifest.js +4 -5
- package/dist/runtime/types.d.ts +18 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/setup/setup-renderer.d.ts +3 -4
- package/dist/setup/setup-renderer.d.ts.map +1 -1
- package/dist/setup/setup-renderer.js +3 -4
- package/dist/world3d-react/engine-bridge.d.ts +1 -1
- package/dist/world3d-react/engine-bridge.js +1 -1
- package/dist/world3d-react/r3f-adapter.d.ts +7 -0
- package/dist/world3d-react/r3f-adapter.d.ts.map +1 -1
- package/dist/world3d-react/r3f-adapter.js +50 -21
- package/dist/world3d-react/r3f-root-factory.d.ts.map +1 -1
- package/dist/world3d-react/r3f-root-factory.js +4 -0
- package/dist/world3d-react/world-context.d.ts +9 -3
- package/dist/world3d-react/world-context.d.ts.map +1 -1
- package/dist/world3d-react/world-context.js +5 -18
- package/package.json +1 -1
- package/schemas/engine-capabilities.json +7 -7
- package/src/adapter/adapter-module.ts +407 -50
- package/src/adapter/authoring-seam-contract.ts +211 -0
- package/src/adapter/authoring.ts +242 -50
- package/src/adapter/entrypoint-selection-source.ts +159 -0
- package/src/adapter/finders/scenes-from-entrypoint-selection.ts +159 -28
- package/src/adapter/first-party-systems.ts +17 -3
- package/src/adapter/index.ts +51 -1
- package/src/adapter/ingest/contract-system-adapters.ts +26 -30
- package/src/adapter/ingest/game-contract-seams.ts +85 -0
- package/src/adapter/ingest/game-contract.ts +9 -4
- package/src/adapter/ingest/merge-debug-adapters.ts +193 -0
- package/src/adapter/ingest/observation-debug-adapter.ts +158 -0
- package/src/adapter/ingest/scene-capture.ts +126 -23
- package/src/adapter/ingest/visible-capture-window.ts +63 -9
- package/src/adapter/native-debug-module.ts +307 -0
- package/src/adapter/object3d-authoring-subject.ts +50 -0
- package/src/adapter/root-adapter.ts +21 -56
- package/src/adapter/root-seam-contract.ts +56 -0
- package/src/adapter/seam-evidence.ts +336 -0
- package/src/adapter/setup-three-root-adapter.ts +4 -6
- package/src/adapter/system-adapter.ts +6 -1
- package/src/adapter/system-seam-contract.ts +121 -0
- package/src/animation/xstate-animation-binding.ts +151 -4
- package/src/canvas-react/engine-bridge.ts +6 -6
- package/src/canvas-react/index.ts +2 -1
- package/src/canvas-react/pixi-react-adapter.tsx +55 -34
- package/src/canvas-react/pixi-react-root-factory.tsx +4 -0
- package/src/canvas-react/world-context.ts +26 -101
- package/src/ecs/user-data.ts +5 -0
- package/src/input/input-manager.ts +122 -0
- package/src/pixi/authoring.ts +236 -1
- package/src/pixi/ingest.ts +9 -2
- package/src/pixi/scene-capture.ts +20 -5
- package/src/render/particles-factory.ts +16 -6
- package/src/runtime/create-runtime.ts +41 -106
- package/src/runtime/game.ts +41 -111
- package/src/runtime/mount-game.ts +19 -1
- package/src/runtime/mount-manifest.ts +4 -5
- package/src/runtime/types.ts +22 -0
- package/src/setup/setup-renderer.ts +3 -4
- package/src/world3d-react/engine-bridge.ts +1 -1
- package/src/world3d-react/r3f-adapter.tsx +64 -24
- package/src/world3d-react/r3f-root-factory.tsx +4 -0
- package/src/world3d-react/world-context.ts +11 -36
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/** Compiler-derived proof requirements for the AuthoringAdapter protocol.
|
|
2
|
+
*
|
|
3
|
+
* This is intentionally adjacent to the interface. Coverage used to enumerate
|
|
4
|
+
* only top-level provider names, which allowed `{}` to count as a complete
|
|
5
|
+
* provider. These descriptors cover every nested member and encode the
|
|
6
|
+
* weakest evidence that can truthfully verify it.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
AssetDropProvider,
|
|
11
|
+
AssetSubjectProvider,
|
|
12
|
+
AuthoringAdapter,
|
|
13
|
+
BoxEditProvider,
|
|
14
|
+
ColorSampleProvider,
|
|
15
|
+
ComponentInstancesProvider,
|
|
16
|
+
HierarchyProvider,
|
|
17
|
+
InspectorProvider,
|
|
18
|
+
PersistenceProvider,
|
|
19
|
+
PickProvider,
|
|
20
|
+
RectProvider,
|
|
21
|
+
RelatedSubjectsProvider,
|
|
22
|
+
SelectionProvider,
|
|
23
|
+
SpatialHandlesProvider,
|
|
24
|
+
StoriesProvider,
|
|
25
|
+
StructureProvider,
|
|
26
|
+
TextProvider,
|
|
27
|
+
TransformProvider,
|
|
28
|
+
TruthProvider,
|
|
29
|
+
} from './authoring';
|
|
30
|
+
import { defineSeamShape, type SeamShape } from './seam-evidence';
|
|
31
|
+
|
|
32
|
+
export const AUTHORING_ADAPTER_SHAPE = defineSeamShape<AuthoringAdapter>()({
|
|
33
|
+
capabilities: { optional: false, kind: 'value', required: 'shape' },
|
|
34
|
+
provenance: { optional: true, kind: 'value', required: 'shape' },
|
|
35
|
+
hierarchy: { optional: false, kind: 'value', required: 'operation' },
|
|
36
|
+
selection: { optional: true, kind: 'value', required: 'effect' },
|
|
37
|
+
transforms: { optional: true, kind: 'value', required: 'effect' },
|
|
38
|
+
inspector: { optional: true, kind: 'value', required: 'effect' },
|
|
39
|
+
assetSubject: { optional: true, kind: 'value', required: 'operation' },
|
|
40
|
+
related: { optional: true, kind: 'value', required: 'operation' },
|
|
41
|
+
instances: { optional: true, kind: 'value', required: 'effect' },
|
|
42
|
+
structure: { optional: true, kind: 'value', required: 'round-trip' },
|
|
43
|
+
persistence: { optional: true, kind: 'value', required: 'round-trip' },
|
|
44
|
+
pickable: { optional: true, kind: 'value', required: 'operation' },
|
|
45
|
+
rects: { optional: true, kind: 'value', required: 'operation' },
|
|
46
|
+
boxEdit: { optional: true, kind: 'value', required: 'effect' },
|
|
47
|
+
text: { optional: true, kind: 'value', required: 'effect' },
|
|
48
|
+
colorSample: { optional: true, kind: 'value', required: 'operation' },
|
|
49
|
+
stories: { optional: true, kind: 'value', required: 'effect' },
|
|
50
|
+
truth: { optional: true, kind: 'value', required: 'operation' },
|
|
51
|
+
spatialHandles: { optional: true, kind: 'value', required: 'effect' },
|
|
52
|
+
assetDrop: { optional: true, kind: 'value', required: 'round-trip' },
|
|
53
|
+
subscribe: { optional: true, kind: 'function', required: 'effect' },
|
|
54
|
+
observeTransforms: { optional: true, kind: 'function', required: 'effect' },
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
export const HIERARCHY_PROVIDER_SHAPE = defineSeamShape<HierarchyProvider>()({
|
|
58
|
+
roots: { optional: false, kind: 'function', required: 'operation' },
|
|
59
|
+
node: { optional: false, kind: 'function', required: 'operation' },
|
|
60
|
+
object3D: { optional: true, kind: 'function', required: 'operation' },
|
|
61
|
+
idForObject3D: { optional: true, kind: 'function', required: 'effect' },
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export const SELECTION_PROVIDER_SHAPE = defineSeamShape<SelectionProvider>()({
|
|
65
|
+
get: { optional: false, kind: 'function', required: 'operation' },
|
|
66
|
+
set: { optional: false, kind: 'function', required: 'effect' },
|
|
67
|
+
resolve: { optional: true, kind: 'function', required: 'operation' },
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
export const TRANSFORM_PROVIDER_SHAPE = defineSeamShape<TransformProvider>()({
|
|
71
|
+
dimensions: { optional: true, kind: 'function', required: 'operation' },
|
|
72
|
+
get: { optional: false, kind: 'function', required: 'operation' },
|
|
73
|
+
editability: { optional: true, kind: 'function', required: 'operation' },
|
|
74
|
+
beginEdit: { optional: false, kind: 'function', required: 'effect' },
|
|
75
|
+
apply: { optional: false, kind: 'function', required: 'effect' },
|
|
76
|
+
endEdit: { optional: false, kind: 'function', required: 'effect' },
|
|
77
|
+
remove: { optional: true, kind: 'function', required: 'round-trip' },
|
|
78
|
+
sourceCommit: { optional: true, kind: 'value', required: 'round-trip' },
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
export const INSPECTOR_PROVIDER_SHAPE = defineSeamShape<InspectorProvider>()({
|
|
82
|
+
properties: { optional: false, kind: 'function', required: 'operation' },
|
|
83
|
+
get: { optional: false, kind: 'function', required: 'operation' },
|
|
84
|
+
set: { optional: false, kind: 'function', required: 'effect' },
|
|
85
|
+
editability: { optional: true, kind: 'function', required: 'operation' },
|
|
86
|
+
remove: { optional: true, kind: 'function', required: 'round-trip' },
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
export const ASSET_SUBJECT_PROVIDER_SHAPE = defineSeamShape<AssetSubjectProvider>()({
|
|
90
|
+
get: { optional: false, kind: 'function', required: 'operation' },
|
|
91
|
+
entries: { optional: true, kind: 'function', required: 'operation' },
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
export const RELATED_SUBJECTS_PROVIDER_SHAPE = defineSeamShape<RelatedSubjectsProvider>()({
|
|
95
|
+
links: { optional: false, kind: 'function', required: 'operation' },
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
export const COMPONENT_INSTANCES_PROVIDER_SHAPE = defineSeamShape<ComponentInstancesProvider>()({
|
|
99
|
+
describe: { optional: false, kind: 'function', required: 'operation' },
|
|
100
|
+
openComponent: { optional: true, kind: 'function', required: 'effect' },
|
|
101
|
+
revert: { optional: false, kind: 'function', required: 'round-trip' },
|
|
102
|
+
applyToComponent: { optional: false, kind: 'function', required: 'round-trip' },
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
export const STRUCTURE_PROVIDER_SHAPE = defineSeamShape<StructureProvider>()({
|
|
106
|
+
create: { optional: false, kind: 'function', required: 'round-trip' },
|
|
107
|
+
remove: { optional: false, kind: 'function', required: 'round-trip' },
|
|
108
|
+
duplicate: { optional: false, kind: 'function', required: 'round-trip' },
|
|
109
|
+
reparent: { optional: false, kind: 'function', required: 'round-trip' },
|
|
110
|
+
reorder: { optional: true, kind: 'function', required: 'round-trip' },
|
|
111
|
+
creatableKinds: { optional: true, kind: 'function', required: 'operation' },
|
|
112
|
+
wrap: { optional: true, kind: 'function', required: 'round-trip' },
|
|
113
|
+
unwrap: { optional: true, kind: 'function', required: 'round-trip' },
|
|
114
|
+
group: { optional: true, kind: 'function', required: 'round-trip' },
|
|
115
|
+
ungroup: { optional: true, kind: 'function', required: 'round-trip' },
|
|
116
|
+
canUngroup: { optional: true, kind: 'function', required: 'operation' },
|
|
117
|
+
removeMany: { optional: true, kind: 'function', required: 'round-trip' },
|
|
118
|
+
copy: { optional: true, kind: 'function', required: 'effect' },
|
|
119
|
+
canCopy: { optional: true, kind: 'function', required: 'operation' },
|
|
120
|
+
cut: { optional: true, kind: 'function', required: 'round-trip' },
|
|
121
|
+
paste: { optional: true, kind: 'function', required: 'round-trip' },
|
|
122
|
+
canPaste: { optional: true, kind: 'function', required: 'operation' },
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
export const PERSISTENCE_PROVIDER_SHAPE = defineSeamShape<PersistenceProvider>()({
|
|
126
|
+
isDirty: { optional: false, kind: 'function', required: 'operation' },
|
|
127
|
+
lastError: { optional: true, kind: 'function', required: 'operation' },
|
|
128
|
+
save: { optional: false, kind: 'function', required: 'round-trip' },
|
|
129
|
+
destination: { optional: false, kind: 'value', required: 'shape' },
|
|
130
|
+
applyExternal: { optional: true, kind: 'function', required: 'effect' },
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
export const PICK_PROVIDER_SHAPE = defineSeamShape<PickProvider>()({
|
|
134
|
+
pick: { optional: false, kind: 'function', required: 'operation' },
|
|
135
|
+
candidates: { optional: true, kind: 'function', required: 'operation' },
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
export const STORIES_PROVIDER_SHAPE = defineSeamShape<StoriesProvider>()({
|
|
139
|
+
storiesFor: { optional: false, kind: 'function', required: 'operation' },
|
|
140
|
+
active: { optional: false, kind: 'function', required: 'operation' },
|
|
141
|
+
apply: { optional: false, kind: 'function', required: 'effect' },
|
|
142
|
+
isolate: { optional: true, kind: 'function', required: 'effect' },
|
|
143
|
+
title: { optional: true, kind: 'value', required: 'shape' },
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
export const ASSET_DROP_PROVIDER_SHAPE = defineSeamShape<AssetDropProvider>()({
|
|
147
|
+
accepts: { optional: false, kind: 'function', required: 'operation' },
|
|
148
|
+
drop: { optional: false, kind: 'function', required: 'round-trip' },
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
export const RECT_PROVIDER_SHAPE = defineSeamShape<RectProvider>()({
|
|
152
|
+
rect: { optional: false, kind: 'function', required: 'operation' },
|
|
153
|
+
contextRects: { optional: true, kind: 'function', required: 'operation' },
|
|
154
|
+
emptyContainers: { optional: true, kind: 'function', required: 'operation' },
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
export const BOX_EDIT_PROVIDER_SHAPE = defineSeamShape<BoxEditProvider>()({
|
|
158
|
+
begin: { optional: false, kind: 'function', required: 'effect' },
|
|
159
|
+
apply: { optional: false, kind: 'function', required: 'effect' },
|
|
160
|
+
end: { optional: false, kind: 'function', required: 'effect' },
|
|
161
|
+
gizmoOrigin: { optional: true, kind: 'function', required: 'operation' },
|
|
162
|
+
referencePoint: { optional: true, kind: 'function', required: 'operation' },
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
export const TEXT_PROVIDER_SHAPE = defineSeamShape<TextProvider>()({
|
|
166
|
+
get: { optional: false, kind: 'function', required: 'operation' },
|
|
167
|
+
set: { optional: false, kind: 'function', required: 'effect' },
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
export const COLOR_SAMPLE_PROVIDER_SHAPE = defineSeamShape<ColorSampleProvider>()({
|
|
171
|
+
backgroundChainAt: { optional: false, kind: 'function', required: 'operation' },
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
export const TRUTH_PROVIDER_SHAPE = defineSeamShape<TruthProvider>()({
|
|
175
|
+
resolve: { optional: false, kind: 'function', required: 'operation' },
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
export const SPATIAL_HANDLES_PROVIDER_SHAPE = defineSeamShape<SpatialHandlesProvider>()({
|
|
179
|
+
layers: { optional: false, kind: 'function', required: 'operation' },
|
|
180
|
+
preview: { optional: false, kind: 'function', required: 'effect' },
|
|
181
|
+
commit: { optional: false, kind: 'function', required: 'round-trip' },
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
type ObjectProviderKey = Exclude<
|
|
185
|
+
keyof AuthoringAdapter,
|
|
186
|
+
'capabilities' | 'provenance' | 'hierarchy' | 'subscribe' | 'observeTransforms'
|
|
187
|
+
>;
|
|
188
|
+
|
|
189
|
+
/** The one nested-provider table. Its key type comes from AuthoringAdapter and
|
|
190
|
+
* each value is typed against that provider's own interface. */
|
|
191
|
+
export const AUTHORING_PROVIDER_SHAPES: {
|
|
192
|
+
readonly [K in ObjectProviderKey]: SeamShape<NonNullable<AuthoringAdapter[K]>>;
|
|
193
|
+
} = {
|
|
194
|
+
selection: SELECTION_PROVIDER_SHAPE,
|
|
195
|
+
transforms: TRANSFORM_PROVIDER_SHAPE,
|
|
196
|
+
inspector: INSPECTOR_PROVIDER_SHAPE,
|
|
197
|
+
assetSubject: ASSET_SUBJECT_PROVIDER_SHAPE,
|
|
198
|
+
related: RELATED_SUBJECTS_PROVIDER_SHAPE,
|
|
199
|
+
instances: COMPONENT_INSTANCES_PROVIDER_SHAPE,
|
|
200
|
+
structure: STRUCTURE_PROVIDER_SHAPE,
|
|
201
|
+
persistence: PERSISTENCE_PROVIDER_SHAPE,
|
|
202
|
+
pickable: PICK_PROVIDER_SHAPE,
|
|
203
|
+
rects: RECT_PROVIDER_SHAPE,
|
|
204
|
+
boxEdit: BOX_EDIT_PROVIDER_SHAPE,
|
|
205
|
+
text: TEXT_PROVIDER_SHAPE,
|
|
206
|
+
colorSample: COLOR_SAMPLE_PROVIDER_SHAPE,
|
|
207
|
+
stories: STORIES_PROVIDER_SHAPE,
|
|
208
|
+
truth: TRUTH_PROVIDER_SHAPE,
|
|
209
|
+
spatialHandles: SPATIAL_HANDLES_PROVIDER_SHAPE,
|
|
210
|
+
assetDrop: ASSET_DROP_PROVIDER_SHAPE,
|
|
211
|
+
};
|
package/src/adapter/authoring.ts
CHANGED
|
@@ -58,7 +58,7 @@ export interface AuthoringProvenance {
|
|
|
58
58
|
* - `foreign` — a live tree the editor does not own (an unmodified external
|
|
59
59
|
* game, or any world edited only through an overlay); edits go to the
|
|
60
60
|
* overlay, never the source;
|
|
61
|
-
* - `live` — a running game adopted at play time; edits are not persisted;
|
|
61
|
+
* - `live` — a running game adopted at play time; ordinary edits are not persisted;
|
|
62
62
|
* - `boundary` — a declared world with no live editing surface here.
|
|
63
63
|
*/
|
|
64
64
|
source: 'document' | 'source-code' | 'foreign' | 'live' | 'boundary';
|
|
@@ -118,6 +118,12 @@ export interface PropertyDescriptor {
|
|
|
118
118
|
label: string;
|
|
119
119
|
type: 'string' | 'number' | 'boolean' | 'vec3' | 'color' | 'enum' | 'asset' | 'json';
|
|
120
120
|
readonly?: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Why this field cannot be written, in the adapter's own vocabulary. The
|
|
123
|
+
* Inspector, its control surface, and the write refusal all project this
|
|
124
|
+
* same sentence; omitting it uses the generic read-only explanation.
|
|
125
|
+
*/
|
|
126
|
+
readonlyReason?: string;
|
|
121
127
|
options?: unknown[];
|
|
122
128
|
/**
|
|
123
129
|
* Optional domain-shaped grouping (T3.4 slice 2): properties sharing the
|
|
@@ -210,6 +216,42 @@ export interface TransformEditability {
|
|
|
210
216
|
writable: boolean;
|
|
211
217
|
/** Human-facing explanation for a disabled gizmo/field. */
|
|
212
218
|
reason?: string;
|
|
219
|
+
/**
|
|
220
|
+
* Is there an AUTHORED override of this channel that {@link
|
|
221
|
+
* TransformProvider.remove} could drop? The per-channel analogue of a
|
|
222
|
+
* property descriptor's `resettable`, and it is answered the same way: the
|
|
223
|
+
* document actually carries this channel, and this session has a door that
|
|
224
|
+
* can take it back.
|
|
225
|
+
*
|
|
226
|
+
* It lives HERE rather than being inferred from `remove`'s presence because
|
|
227
|
+
* `remove` is a lane-wide fact while this is a per-subject one — a composite
|
|
228
|
+
* routes both, but only this one can say that THIS node's `position` is
|
|
229
|
+
* authored and THAT node's is not. Omitted ⇒ nothing to drop, and the
|
|
230
|
+
* protocol's removal door refuses by name instead of acking a revert it did
|
|
231
|
+
* not perform.
|
|
232
|
+
*
|
|
233
|
+
* EACH HALF IS ANSWERED BY WHOEVER CAN SEE IT, and a lane that cannot read
|
|
234
|
+
* its own document may not invent the first. A source lane holding the
|
|
235
|
+
* file's text answers both (the first-party R3F lane reads the callsite's
|
|
236
|
+
* attributes before saying yes). A lane whose client holds only an
|
|
237
|
+
* oid → file:line index and writes through a server that resolves the
|
|
238
|
+
* address — the vendored-ingest lane — can honestly answer only the SECOND,
|
|
239
|
+
* so that is what it answers, and `remove`'s own {@link WriteAck} reports
|
|
240
|
+
* whether an attribute was actually dropped (`persisted: false` when the
|
|
241
|
+
* callsite carried none). The inverse is what is forbidden on every lane:
|
|
242
|
+
* acking a drop that took no byte.
|
|
243
|
+
*/
|
|
244
|
+
removable?: boolean;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** The one lawful Play→source write: a person explicitly attributes the
|
|
248
|
+
* selected live node's current transform to its OID-anchored source literal.
|
|
249
|
+
* This is an atomic optional group so availability and the write door cannot
|
|
250
|
+
* drift apart. Ordinary transform gestures remain governed by begin/apply/end
|
|
251
|
+
* and therefore stay ephemeral while Play is running. */
|
|
252
|
+
export interface TransformSourceCommitProvider {
|
|
253
|
+
availability(id: string): { available: boolean; reason?: string };
|
|
254
|
+
commit(id: string): Promise<WriteAck>;
|
|
213
255
|
}
|
|
214
256
|
|
|
215
257
|
export interface TransformProvider {
|
|
@@ -231,6 +273,35 @@ export interface TransformProvider {
|
|
|
231
273
|
* live-only floor rather than borrowing an answer from somewhere else.
|
|
232
274
|
*/
|
|
233
275
|
endEdit(id: string): void | WriteAck | Promise<void | WriteAck>;
|
|
276
|
+
/**
|
|
277
|
+
* Optional — DROP one channel's authored transform entirely, rather than
|
|
278
|
+
* writing a value into it.
|
|
279
|
+
*
|
|
280
|
+
* THE SAME DOOR {@link InspectorProvider.remove} IS, for the channel the
|
|
281
|
+
* Transform section owns instead of a property row. `apply`/`endEdit` write a
|
|
282
|
+
* VALUE, so reverting a channel an authoring gesture APPENDED by writing the
|
|
283
|
+
* old numbers back leaves `position={[0, 0, 0]}` standing where the source
|
|
284
|
+
* carried nothing — the file ends one attribute heavier than it started, and
|
|
285
|
+
* no byte-level edit/revert round trip can close. Only removal expresses that
|
|
286
|
+
* absence, which is why a lane without this door grades UNVERIFIABLE rather
|
|
287
|
+
* than passing.
|
|
288
|
+
*
|
|
289
|
+
* SAME ACK CONTRACT AS {@link endEdit} — the pipe's per-edit {@link WriteAck}
|
|
290
|
+
* for THIS removal, awaited. Removal is a write; it moves bytes, and the
|
|
291
|
+
* caller has the same right to be told where they went. Returning nothing
|
|
292
|
+
* means this provider performed no persisted write and the shell reports the
|
|
293
|
+
* live-only floor.
|
|
294
|
+
*
|
|
295
|
+
* What "absent" MEANS is the dialect writer's to decide (deleting the JSX
|
|
296
|
+
* attribute, for the source lanes). Nothing above this seam infers it: a lane
|
|
297
|
+
* whose transform truth IS the running object — there is no document for the
|
|
298
|
+
* channel to be absent from — simply omits the method, and the protocol door
|
|
299
|
+
* refuses by name rather than falling back to a value write.
|
|
300
|
+
*/
|
|
301
|
+
remove?(id: string, channel: TransformChannel): void | WriteAck | Promise<void | WriteAck>;
|
|
302
|
+
/** Explicit Play→source attribution. Absent outside an eligible live OID
|
|
303
|
+
* surface; never used implicitly by a transform gesture. */
|
|
304
|
+
readonly sourceCommit?: TransformSourceCommitProvider;
|
|
234
305
|
}
|
|
235
306
|
|
|
236
307
|
/**
|
|
@@ -262,14 +333,28 @@ export interface InspectorProvider {
|
|
|
262
333
|
editability?(id: string, path: string): { writable: boolean; reason?: string };
|
|
263
334
|
/**
|
|
264
335
|
* Optional — REMOVE a property's authored override entirely (not "set to a
|
|
265
|
-
* value"), letting whatever governs it in its absence take over.
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
336
|
+
* value"), letting whatever governs it in its absence take over.
|
|
337
|
+
*
|
|
338
|
+
* THIS IS THE ONLY WAY TO EXPRESS BYTE-ABSENCE. {@link set} writes a VALUE:
|
|
339
|
+
* reverting a prop an authoring gesture ADDED by setting it back to what the
|
|
340
|
+
* default would have been leaves `position={[0, 0, 0]}` in the source where
|
|
341
|
+
* the file previously carried nothing at all. Only removal restores the
|
|
342
|
+
* bytes, which is why a lane with no `remove` cannot close its own
|
|
343
|
+
* edit/revert round trip and grades UNVERIFIABLE rather than passing.
|
|
344
|
+
*
|
|
345
|
+
* SAME ACK CONTRACT AS {@link set} — the pipe's per-edit {@link WriteAck}
|
|
346
|
+
* (`editor/src/authoring/write-pipe.ts`), awaited. Removal is a write; it
|
|
347
|
+
* moves bytes, and the caller has the same right to be told where they went
|
|
348
|
+
* and whether they moved. Returning nothing means this provider performed no
|
|
349
|
+
* persisted write, and the shell reports the live-only floor.
|
|
350
|
+
*
|
|
351
|
+
* What "absent" MEANS is the dialect writer's to decide — deleting a JSX
|
|
352
|
+
* attribute, dropping a CSS longhand so its shorthand cascades. Nothing above
|
|
353
|
+
* this seam infers it. Adapters with no removable-override concept simply
|
|
354
|
+
* omit the method; callers optional-chain, and the protocol door refuses by
|
|
355
|
+
* name rather than falling back to a value write.
|
|
271
356
|
*/
|
|
272
|
-
remove?(id: string, path: string): void
|
|
357
|
+
remove?(id: string, path: string): void | WriteAck | Promise<void | WriteAck>;
|
|
273
358
|
}
|
|
274
359
|
|
|
275
360
|
/**
|
|
@@ -340,6 +425,9 @@ export interface ComponentInstanceDescription {
|
|
|
340
425
|
export interface ComponentInstanceApplyResult {
|
|
341
426
|
readonly changed: boolean;
|
|
342
427
|
readonly message: string;
|
|
428
|
+
/** This operation's own writer acknowledgement. Absent when the request was
|
|
429
|
+
* refused before any write; live-only is an explicit WriteAck. */
|
|
430
|
+
readonly write?: WriteAck;
|
|
343
431
|
}
|
|
344
432
|
|
|
345
433
|
/**
|
|
@@ -352,14 +440,84 @@ export interface ComponentInstancesProvider {
|
|
|
352
440
|
describe(id: string): ComponentInstanceDescription | null;
|
|
353
441
|
/** Open the native component/prefab board for this instance's surface. */
|
|
354
442
|
openComponent?(id: string): void;
|
|
355
|
-
revert(id: string, paths: readonly string[]): Promise<void>;
|
|
443
|
+
revert(id: string, paths: readonly string[]): Promise<void | WriteAck>;
|
|
356
444
|
applyToComponent(id: string, path: string): Promise<ComponentInstanceApplyResult>;
|
|
357
445
|
}
|
|
358
446
|
|
|
447
|
+
/**
|
|
448
|
+
* WHAT A STRUCTURAL VERB ANSWERS WITH — the same widening
|
|
449
|
+
* {@link TransformProvider.endEdit} and {@link InspectorProvider.set} carry,
|
|
450
|
+
* for the same reason: the ack is produced by the component that performed
|
|
451
|
+
* THIS edit, and there is nowhere else for a caller to get one.
|
|
452
|
+
*
|
|
453
|
+
* `void` is the honest answer for a lane whose verb performs no write of its
|
|
454
|
+
* own (an in-memory adapter mutating a graph it already owns); a lane that
|
|
455
|
+
* writes returns the persistence pipe's own {@link WriteAck}
|
|
456
|
+
* (`editor/src/authoring/write-pipe.ts`), awaited, so a caller that awaits the
|
|
457
|
+
* verb has awaited the byte.
|
|
458
|
+
*
|
|
459
|
+
* A structural verb resolves on ITS OWN verb: `remove` asks whether the struct
|
|
460
|
+
* writer is bound, never whether the PROP writer is — resolving on a
|
|
461
|
+
* value-write door is how a lane comes to ack `source-prop` for a door it does
|
|
462
|
+
* not have.
|
|
463
|
+
*/
|
|
464
|
+
export type StructuralWriteOutcome = void | WriteAck | Promise<void | WriteAck>;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* WHAT AN ID-RETURNING STRUCTURAL VERB ANSWERS WITH — the id and the ack, as
|
|
468
|
+
* ONE return.
|
|
469
|
+
*
|
|
470
|
+
* The writing verbs ({@link StructureProvider.remove} and friends) answer with
|
|
471
|
+
* a bare {@link StructuralWriteOutcome}, because the write IS their whole
|
|
472
|
+
* answer. `create`/`duplicate`/`group`/`ungroup` owe their caller a second
|
|
473
|
+
* thing — the id(s) the op produced — and those two halves settle at DIFFERENT
|
|
474
|
+
* TIMES:
|
|
475
|
+
*
|
|
476
|
+
* - the id is SYNCHRONOUS where a lane can mint one. The live canvas surface
|
|
477
|
+
* adds a real display object to the running tree and re-indexes before it
|
|
478
|
+
* returns, so `create` hands back an id its caller can select in the same
|
|
479
|
+
* turn ("create then immediately select it" is the ordinary shell
|
|
480
|
+
* sequence). Making the verb `async` to carry the ack would take that
|
|
481
|
+
* away from every caller to serve a value that is already known.
|
|
482
|
+
* - the ack is ASYNCHRONOUS wherever a byte is involved, and it is the only
|
|
483
|
+
* thing that says whether the edit reached the file it claims.
|
|
484
|
+
*
|
|
485
|
+
* So the return carries both. A source lane whose new id only exists after the
|
|
486
|
+
* remount stamps it answers `id: ''` (there is no honest synchronous id) with a
|
|
487
|
+
* real `ack`; a router that could not route answers with an unchanged id and
|
|
488
|
+
* `ack: undefined` (no write was attempted, which is exactly what `void` means
|
|
489
|
+
* in {@link StructuralWriteOutcome}).
|
|
490
|
+
*
|
|
491
|
+
* Firing the write and dropping the promise on the floor — `void structOp(…)`
|
|
492
|
+
* behind a `return ''` — is the shape this type exists to make unrepresentable:
|
|
493
|
+
* it left the caller unable to await the byte, which is how N same-file
|
|
494
|
+
* duplicates went out together, each reading the file before any wrote back.
|
|
495
|
+
*/
|
|
496
|
+
export interface StructuralIdWrite<Id extends string | null = string> {
|
|
497
|
+
/** The id the op produced — `''` when the lane cannot know it until its own
|
|
498
|
+
* source write completes and the world remounts. */
|
|
499
|
+
readonly id: Id;
|
|
500
|
+
readonly ack: StructuralWriteOutcome;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/** The plural half of {@link StructuralIdWrite}, for a verb that promotes a set
|
|
504
|
+
* of ids rather than minting one. */
|
|
505
|
+
export interface StructuralIdsWrite {
|
|
506
|
+
readonly ids: readonly string[];
|
|
507
|
+
readonly ack: StructuralWriteOutcome;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/** Clipboard-backed structural writes retain the existing `false` refusal
|
|
511
|
+
* channel while answering a successful cut/paste with the write's real
|
|
512
|
+
* destination. A bare `true` cannot prove a byte landed anywhere. */
|
|
513
|
+
export type StructuralClipboardOutcome = false | WriteAck | Promise<false | WriteAck>;
|
|
514
|
+
|
|
359
515
|
export interface StructureProvider {
|
|
360
|
-
|
|
516
|
+
/** Create a `kind` under `parentId`, answering with the new id AND this
|
|
517
|
+
* creation's own write ack (see {@link StructuralIdWrite}). */
|
|
518
|
+
create(kind: string, parentId?: string): StructuralIdWrite;
|
|
361
519
|
/**
|
|
362
|
-
* Remove `id`. May optionally return an awaitable
|
|
520
|
+
* Remove `id`. May optionally return an awaitable when the
|
|
363
521
|
* underlying write is asynchronous (e.g. a react-world source-file edit) —
|
|
364
522
|
* `deleteSelection` (`editor-hotkeys.ts`) awaits it per id so a same-file
|
|
365
523
|
* multi-delete's writes land strictly one at a time (see that function's own
|
|
@@ -367,14 +525,22 @@ export interface StructureProvider {
|
|
|
367
525
|
* a per-id loop sound for an adapter whose OID index isn't reindexed between
|
|
368
526
|
* writes). An adapter with a synchronous/in-memory remove (e.g.
|
|
369
527
|
* `UIAuthoringAdapter`) returns `void` — `await`ing it is a harmless no-op.
|
|
528
|
+
*
|
|
529
|
+
* A source-writing lane returns THIS removal's own {@link WriteAck} (see
|
|
530
|
+
* {@link StructuralWriteOutcome}).
|
|
370
531
|
*/
|
|
371
|
-
remove(id: string):
|
|
372
|
-
|
|
373
|
-
|
|
532
|
+
remove(id: string): StructuralWriteOutcome;
|
|
533
|
+
/** Copy `id`, answering with the copy's id AND this duplication's own write
|
|
534
|
+
* ack (see {@link StructuralIdWrite}). A source lane whose copy has no id
|
|
535
|
+
* until the remount stamps it answers with the SOURCE id it was given —
|
|
536
|
+
* `duplicate` has no refusal channel, so an empty string there would be
|
|
537
|
+
* indistinguishable from "refused". */
|
|
538
|
+
duplicate(id: string): StructuralIdWrite;
|
|
539
|
+
reparent(id: string, newParentId: string | null): StructuralWriteOutcome;
|
|
374
540
|
/** Reorder `id` to sit immediately before `beforeSiblingId` among its siblings
|
|
375
541
|
* (`null` = move to the end). Absent ⇒ the shell has no sibling-reorder UI
|
|
376
542
|
* for this adapter. */
|
|
377
|
-
reorder?(id: string, beforeSiblingId: string | null):
|
|
543
|
+
reorder?(id: string, beforeSiblingId: string | null): StructuralWriteOutcome;
|
|
378
544
|
/**
|
|
379
545
|
* The kinds `create` accepts for a given parent (`null` parentId = a new
|
|
380
546
|
* root), each with a display label — drives the shell's creation palette.
|
|
@@ -387,18 +553,22 @@ export interface StructureProvider {
|
|
|
387
553
|
* adapter-chosen, e.g. a `div`), re-parenting `id` as that container's sole
|
|
388
554
|
* child. Absent ⇒ the shell's context menu shows no Wrap item for this
|
|
389
555
|
* adapter. */
|
|
390
|
-
wrap?(id: string, wrapperTag?: string):
|
|
556
|
+
wrap?(id: string, wrapperTag?: string): StructuralWriteOutcome;
|
|
391
557
|
/** D3 (spec 27 §6) — replace `id` with its own children (the inverse of
|
|
392
558
|
* `wrap`). Absent ⇒ the shell's context menu shows no Unwrap item for this
|
|
393
559
|
* adapter. */
|
|
394
|
-
unwrap?(id: string):
|
|
560
|
+
unwrap?(id: string): StructuralWriteOutcome;
|
|
395
561
|
/** Group sibling authoring objects beneath one new spatial parent. The
|
|
396
562
|
* adapter owns transform preservation, persistence, and undo semantics.
|
|
397
|
-
*
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
563
|
+
* Answers with the new group id — `null` when the selection cannot be
|
|
564
|
+
* grouped at all — AND this grouping's own write ack (see
|
|
565
|
+
* {@link StructuralIdWrite}). */
|
|
566
|
+
group?(ids: readonly string[]): StructuralIdWrite<string | null>;
|
|
567
|
+
/** Dissolve a plain spatial group, answering with the ids of its promoted
|
|
568
|
+
* children AND this dissolution's own write ack (see
|
|
569
|
+
* {@link StructuralIdsWrite}). Absent means this adapter has no lossless
|
|
570
|
+
* ungroup operation. */
|
|
571
|
+
ungroup?(id: string): StructuralIdsWrite;
|
|
402
572
|
/** Preflight for an Ungroup affordance. Omit when ungroup is never offered. */
|
|
403
573
|
canUngroup?(id: string): boolean;
|
|
404
574
|
/**
|
|
@@ -410,15 +580,15 @@ export interface StructureProvider {
|
|
|
410
580
|
* own single batched multi-delete undo). Absent ⇒ the shell falls back to
|
|
411
581
|
* the per-id `remove` loop (today's N-entry behavior, unchanged) — an
|
|
412
582
|
* honest degrade, not a silent behavior change, for any adapter that
|
|
413
|
-
* hasn't implemented batching. May optionally return an awaitable
|
|
414
|
-
*
|
|
415
|
-
* same reason (delete-order-residual fix): `deleteSelection`
|
|
583
|
+
* hasn't implemented batching. May optionally return an awaitable, same
|
|
584
|
+
* widening `remove` documents above ({@link StructuralWriteOutcome}) and for
|
|
585
|
+
* the same reason (delete-order-residual fix): `deleteSelection`
|
|
416
586
|
* (`editor-hotkeys.ts`) awaits it so the caller can rely on the whole
|
|
417
587
|
* batch's write having landed before it returns. A synchronous/in-memory
|
|
418
588
|
* implementation (e.g. `UIAuthoringAdapter`'s) returns `void` — awaiting it
|
|
419
589
|
* is a harmless no-op.
|
|
420
590
|
*/
|
|
421
|
-
removeMany?(ids: readonly string[]):
|
|
591
|
+
removeMany?(ids: readonly string[]): StructuralWriteOutcome;
|
|
422
592
|
/** Copy authored entities through the host clipboard. The adapter owns the
|
|
423
593
|
* native payload (JSX for a source-backed Three/Canvas world, native records
|
|
424
594
|
* for a data-backed adapter); the shell never serializes an engine-private
|
|
@@ -428,11 +598,11 @@ export interface StructureProvider {
|
|
|
428
598
|
canCopy?(ids: readonly string[]): boolean;
|
|
429
599
|
/** Copy, then remove the same authored entities only after the clipboard
|
|
430
600
|
* write succeeds. One adapter operation owns that ordering. */
|
|
431
|
-
cut?(ids: readonly string[]):
|
|
601
|
+
cut?(ids: readonly string[]): StructuralClipboardOutcome;
|
|
432
602
|
/** Paste as children of `parentId`; `null` means the adapter document root.
|
|
433
603
|
* The shell derives the current selection's parent so ordinary Paste creates
|
|
434
604
|
* siblings, matching scene-hierarchy editors. */
|
|
435
|
-
paste?(parentId: string | null):
|
|
605
|
+
paste?(parentId: string | null): StructuralClipboardOutcome;
|
|
436
606
|
/** Honest affordance preflight. It need only cover adapter/session state;
|
|
437
607
|
* the actual paste still validates the live system clipboard. */
|
|
438
608
|
canPaste?(parentId: string | null): boolean;
|
|
@@ -538,7 +708,11 @@ export interface AssetDropContext {
|
|
|
538
708
|
/** Asset drop (hierarchy + viewport). */
|
|
539
709
|
export interface AssetDropProvider {
|
|
540
710
|
accepts(nodeId: string, assetPath: string, context?: AssetDropContext): boolean;
|
|
541
|
-
drop
|
|
711
|
+
/** A drop that lands as an ELEMENT in the game's own source is a structural
|
|
712
|
+
* write, so it answers with the same {@link StructuralWriteOutcome} the rest
|
|
713
|
+
* of {@link StructureProvider}'s writing verbs do — a lane whose drop only
|
|
714
|
+
* mutates the running graph returns `void`. */
|
|
715
|
+
drop(nodeId: string, assetPath: string, context?: AssetDropContext): StructuralWriteOutcome;
|
|
542
716
|
}
|
|
543
717
|
|
|
544
718
|
/** Plain-object rect shape shared by {@link RectProvider} — the same fields a real
|
|
@@ -708,6 +882,19 @@ export type NodeCreationSite =
|
|
|
708
882
|
* the anchor; survives a cold remount, because the file is truth and the next
|
|
709
883
|
* mount re-derives from it.
|
|
710
884
|
* Proof: `packages/editor/test/oid-source-persistence.test.ts`.
|
|
885
|
+
* - `source-structure` — the edit is not a VALUE at all: it adds, removes,
|
|
886
|
+
* moves or re-nests an ELEMENT of the game's own source (`delete`,
|
|
887
|
+
* `duplicate`, `wrap`/`unwrap`, `create`, `reorder`, `reparent`, `group`).
|
|
888
|
+
* It is a kind rather than a flavour of `source-prop` because it resolves on
|
|
889
|
+
* a DIFFERENT DOOR — the dialect's structural writer, not its attribute
|
|
890
|
+
* writer — and a lane can have one without the other. Claiming `source-prop`
|
|
891
|
+
* for a structural edit is exactly the classifier/writer split the
|
|
892
|
+
* persistence pipe exists to make impossible: it names a value lane that
|
|
893
|
+
* never carried the bytes. Its landing contract adds one gate the prop lane
|
|
894
|
+
* does not have: the write is WHOLE-FILE and checksum-guarded, so an op
|
|
895
|
+
* resolved against a stale element index must fail rather than land at the
|
|
896
|
+
* wrong offset.
|
|
897
|
+
* Proof: `packages/editor/test/structural-write-pipe.test.ts`.
|
|
711
898
|
* - `construction-literal` — the value is a literal in the CONSTRUCTION
|
|
712
899
|
* EXPRESSION that built the object (`new THREE.Mesh(…)` in the game's own
|
|
713
900
|
* served module). Same landing/remount contract, plus one gate the prop lane
|
|
@@ -740,6 +927,7 @@ export type NodeCreationSite =
|
|
|
740
927
|
*/
|
|
741
928
|
export type WriteAnchorKind =
|
|
742
929
|
| 'source-prop'
|
|
930
|
+
| 'source-structure'
|
|
743
931
|
| 'construction-literal'
|
|
744
932
|
| 'physics-binding'
|
|
745
933
|
| 'data-record'
|
|
@@ -793,6 +981,7 @@ export interface WriteAck {
|
|
|
793
981
|
*/
|
|
794
982
|
const WRITE_ANCHOR_KIND_PRESENCE: Readonly<Record<WriteAnchorKind, true>> = {
|
|
795
983
|
'source-prop': true,
|
|
984
|
+
'source-structure': true,
|
|
796
985
|
'construction-literal': true,
|
|
797
986
|
'physics-binding': true,
|
|
798
987
|
'data-record': true,
|
|
@@ -824,22 +1013,23 @@ export function emptyWriteAnchorKindCounts(): Record<WriteAnchorKind, number> {
|
|
|
824
1013
|
* document-backed world's truth is the document, not a construction site).
|
|
825
1014
|
* Present ⇒ every id gets an answer, anchored or reasoned.
|
|
826
1015
|
*/
|
|
827
|
-
export interface
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
*
|
|
832
|
-
*
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
1016
|
+
export interface AuthoringTruth {
|
|
1017
|
+
/** Where the runtime object came from in the game's own source or data. */
|
|
1018
|
+
readonly site: NodeCreationSite;
|
|
1019
|
+
/** The lane THIS property edit would actually take. `undefined` means the
|
|
1020
|
+
* subject is synthetic or otherwise has no write plan; `live-only` is a real
|
|
1021
|
+
* plan whose destination is the running object. */
|
|
1022
|
+
readonly writeAnchorKind: WriteAnchorKind | undefined;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* The TRUTH-family binding. One resolution answers both where a subject came
|
|
1027
|
+
* from and where an edit to one of its properties lands. A caller may not read
|
|
1028
|
+
* those facts through separate providers: that was the classifier/writer split
|
|
1029
|
+
* the persistence pipe exists to remove.
|
|
1030
|
+
*/
|
|
1031
|
+
export interface TruthProvider {
|
|
1032
|
+
resolve(id: string, property: string): AuthoringTruth;
|
|
843
1033
|
}
|
|
844
1034
|
|
|
845
1035
|
/** A plain world-space point. Component handles cross the authoring seam as
|
|
@@ -931,7 +1121,10 @@ export interface SpatialHandleLayer {
|
|
|
931
1121
|
export interface SpatialHandlesProvider {
|
|
932
1122
|
layers(id: string): readonly SpatialHandleLayer[];
|
|
933
1123
|
preview(id: string, handleId: string, worldPosition: SpatialPoint3): void;
|
|
934
|
-
|
|
1124
|
+
/** Commit the preview and pass through the owning writer's acknowledgement.
|
|
1125
|
+
* `void` remains the honest live-only/no-write floor; callers must not grade
|
|
1126
|
+
* it as a persisted round trip. */
|
|
1127
|
+
commit(id: string, handleId: string, worldPosition: SpatialPoint3): StructuralWriteOutcome;
|
|
935
1128
|
}
|
|
936
1129
|
|
|
937
1130
|
export interface AuthoringAdapter {
|
|
@@ -967,9 +1160,8 @@ export interface AuthoringAdapter {
|
|
|
967
1160
|
readonly colorSample?: ColorSampleProvider;
|
|
968
1161
|
/** D4 — storybook stories. Absent ⇒ no stories for any node in this adapter. */
|
|
969
1162
|
readonly stories?: StoriesProvider;
|
|
970
|
-
/**
|
|
971
|
-
|
|
972
|
-
readonly creationSite?: CreationSiteProvider;
|
|
1163
|
+
/** Projection subject → source/data anchor and write lane, resolved together. */
|
|
1164
|
+
readonly truth?: TruthProvider;
|
|
973
1165
|
/** Adapter-owned component guides and direct-manipulation points. */
|
|
974
1166
|
readonly spatialHandles?: SpatialHandlesProvider;
|
|
975
1167
|
/** Asset drop (hierarchy + viewport). Absent ⇒ this adapter accepts no drops. */
|
|
@@ -1030,7 +1222,7 @@ const AUTHORING_PROVIDER_PRESENCE: Readonly<Record<AuthoringProviderKey, true>>
|
|
|
1030
1222
|
text: true,
|
|
1031
1223
|
colorSample: true,
|
|
1032
1224
|
stories: true,
|
|
1033
|
-
|
|
1225
|
+
truth: true,
|
|
1034
1226
|
spatialHandles: true,
|
|
1035
1227
|
assetDrop: true,
|
|
1036
1228
|
subscribe: true,
|