@vgai/editor-sdk 0.5.41 → 0.5.44
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 +2 -2
- package/src/client.ts +339 -49
- package/src/contributions.ts +208 -1
- package/src/document-probe.ts +55 -2
- package/src/editor-view.ts +1 -0
- package/src/index.ts +15 -0
- package/src/types.ts +241 -12
package/src/types.ts
CHANGED
|
@@ -11,6 +11,16 @@ export type ViewportTab = 'edit' | 'play';
|
|
|
11
11
|
|
|
12
12
|
export type AssetKind = 'model' | 'image' | 'audio' | 'animation' | 'json' | 'prefab' | 'source';
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* The editor's NAMED WORKSPACES — task-named layout memories over the one
|
|
16
|
+
* physical dock (ARCHITECTURE-CORE §Editor chrome). Named for the TASK, each
|
|
17
|
+
* borrowing the arrangement of the tool that does it best; `game` is the
|
|
18
|
+
* default and is the editor's standing arrangement. Restated here (rather than
|
|
19
|
+
* imported from the editor) for the same reason every other id union in this
|
|
20
|
+
* file is: the SDK is a wire client and must not depend on the editor bundle.
|
|
21
|
+
*/
|
|
22
|
+
export type EditorWorkspaceName = 'game' | 'model' | 'sculpt' | 'texture' | 'animate' | 'look';
|
|
23
|
+
|
|
14
24
|
export interface HelperVisibility {
|
|
15
25
|
bounds: boolean;
|
|
16
26
|
lights: boolean;
|
|
@@ -50,6 +60,30 @@ export interface ViewportCapture {
|
|
|
50
60
|
mimeType: 'image/png';
|
|
51
61
|
}
|
|
52
62
|
|
|
63
|
+
/**
|
|
64
|
+
* How an animated look move on the open Object3D document ended. Never an
|
|
65
|
+
* error: the camera is SHARED with the person watching, so "they grabbed it
|
|
66
|
+
* mid-orbit" is an outcome to read, not a failure to handle.
|
|
67
|
+
*/
|
|
68
|
+
export interface DocumentLookOutcome {
|
|
69
|
+
/** True only when the whole move was drawn. */
|
|
70
|
+
completed: boolean;
|
|
71
|
+
/** Why it stopped early: a human drag, a later look verb, or a closed document. */
|
|
72
|
+
cancelledBy?: 'human' | 'superseded' | 'closed';
|
|
73
|
+
/** Where the camera ended up, radians around the framed subject. */
|
|
74
|
+
azimuth: number;
|
|
75
|
+
/** Radians above the subject's horizon. */
|
|
76
|
+
elevation: number;
|
|
77
|
+
/** Seconds of the move that were actually drawn. */
|
|
78
|
+
seconds: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Where the open document's camera is standing and what it is aimed at. */
|
|
82
|
+
export interface DocumentCameraPose {
|
|
83
|
+
position: [number, number, number];
|
|
84
|
+
target: [number, number, number];
|
|
85
|
+
}
|
|
86
|
+
|
|
53
87
|
/** Result of the editor's native Asset Lab ragdoll-generation operation. */
|
|
54
88
|
export interface RagdollGenerationResult {
|
|
55
89
|
capability: 'added' | 'present';
|
|
@@ -98,6 +132,15 @@ export interface GameCapture {
|
|
|
98
132
|
/** True when the host loop was starved and the runtime rendered one
|
|
99
133
|
* deterministic tick to produce this frame. */
|
|
100
134
|
loopRecoveryFrame?: boolean;
|
|
135
|
+
/** Present when this frame came out of a RECORDED run (every `vgai play`
|
|
136
|
+
* records). The still is delivered either way; `notice` is the sentence
|
|
137
|
+
* naming the clip, its offset-0 wall clock, and what a still cannot answer —
|
|
138
|
+
* shown verbatim, never re-derived by the caller. */
|
|
139
|
+
recording?: {
|
|
140
|
+
path: string;
|
|
141
|
+
startedAt: string;
|
|
142
|
+
notice: string;
|
|
143
|
+
};
|
|
101
144
|
}
|
|
102
145
|
|
|
103
146
|
/** Options for recording the clean running-game composite. */
|
|
@@ -141,11 +184,30 @@ export interface GameplayRecordingCapture extends GameplayRecordingStarted {
|
|
|
141
184
|
hidden: boolean;
|
|
142
185
|
}
|
|
143
186
|
|
|
187
|
+
/** A position on the active recorder's authoritative monotonic timeline.
|
|
188
|
+
* `startedAt` identifies the recording; `elapsedMs` shares the exact origin
|
|
189
|
+
* used to calculate the finalized capture's `durationMs`. */
|
|
190
|
+
export interface GameplayRecordingTimeline {
|
|
191
|
+
startedAt: string;
|
|
192
|
+
elapsedMs: number;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** What Play can report while its recording is still open. Geometry, layers, media cadence, and
|
|
196
|
+
* final health are deliberately absent: those facts are only authoritative after Stop finalizes
|
|
197
|
+
* the capture. */
|
|
198
|
+
export interface PlayRecordingStatus {
|
|
199
|
+
path: string;
|
|
200
|
+
startedAt: string;
|
|
201
|
+
rotates: boolean;
|
|
202
|
+
logFile: string | null;
|
|
203
|
+
idleAutoStopMs: number;
|
|
204
|
+
}
|
|
205
|
+
|
|
144
206
|
/** What `play` reports back once the run is up and recording. */
|
|
145
207
|
export interface PlayStarted {
|
|
146
208
|
/** Absent only when the recorder could not start; play is up either way and
|
|
147
209
|
* the editor console carries the reason. */
|
|
148
|
-
recording?:
|
|
210
|
+
recording?: PlayRecordingStatus;
|
|
149
211
|
}
|
|
150
212
|
|
|
151
213
|
export type AssetPreviewView = 'front' | 'right' | 'top' | 'perspective';
|
|
@@ -185,16 +247,61 @@ export type AssetPreviewSource =
|
|
|
185
247
|
*/
|
|
186
248
|
export type AssetPreviewStage = 'lab' | 'scene';
|
|
187
249
|
|
|
250
|
+
/**
|
|
251
|
+
* A free capture camera for the Asset Lab legs (`vgai screenshot`'s
|
|
252
|
+
* `--azimuth/--elevation/--distance`): ONE view from a chosen angle instead
|
|
253
|
+
* of the fixed four. Angles are relative to the subject's AUTHORED front —
|
|
254
|
+
* azimuth 0 photographs the declared front, 90 walks toward the side the
|
|
255
|
+
* turntable's yaw-90 shot shows; elevation raises the camera (degrees above
|
|
256
|
+
* level); `distance` is meters from the framing center, auto-fit when
|
|
257
|
+
* omitted.
|
|
258
|
+
*/
|
|
259
|
+
export interface AssetPreviewCameraChoice {
|
|
260
|
+
azimuthDegrees: number;
|
|
261
|
+
elevationDegrees: number;
|
|
262
|
+
distance?: number;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Pose an animated subject before capturing (`vgai screenshot`'s
|
|
267
|
+
* `--clip <name> --time <t>`): the named clip is sampled at `timeSeconds`
|
|
268
|
+
* on the capture's disposable snapshot — the source is never mutated. The
|
|
269
|
+
* capture fails loudly (naming the clips that DO exist) when the subject
|
|
270
|
+
* carries no clip by this name.
|
|
271
|
+
*/
|
|
272
|
+
export interface AssetPreviewPose {
|
|
273
|
+
clip: string;
|
|
274
|
+
timeSeconds: number;
|
|
275
|
+
}
|
|
276
|
+
|
|
188
277
|
export interface AssetPreviewOptions {
|
|
189
278
|
width?: number;
|
|
190
279
|
height?: number;
|
|
191
280
|
background?: AssetPreviewBackground;
|
|
192
281
|
stage?: AssetPreviewStage;
|
|
282
|
+
camera?: AssetPreviewCameraChoice;
|
|
283
|
+
pose?: AssetPreviewPose;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* How the captured subject was oriented relative to its AUTHORED coordinates.
|
|
288
|
+
* The editor yaw-normalizes a subject so the front camera photographs its
|
|
289
|
+
* declared front; a 180-degree yaw maps authored +X to screen-LEFT in the
|
|
290
|
+
* front view. The yaw is reported here (and stamped onto the images' own
|
|
291
|
+
* pixels as `+X>` / `<+X` markers) so it is never applied silently.
|
|
292
|
+
*/
|
|
293
|
+
export interface AssetPreviewOrientation {
|
|
294
|
+
/** The subject's declared forward, `[0,0,1]` when it declares none. */
|
|
295
|
+
forward: [number, number, number];
|
|
296
|
+
/** Yaw applied to face the front camera; 0 means authored axes = world axes. */
|
|
297
|
+
yawDegrees: number;
|
|
193
298
|
}
|
|
194
299
|
|
|
195
300
|
export interface AssetPreviewCapture {
|
|
196
301
|
width: number;
|
|
197
302
|
height: number;
|
|
303
|
+
/** Absent from editors that predate orientation reporting. */
|
|
304
|
+
orientation?: AssetPreviewOrientation;
|
|
198
305
|
views: Array<ViewportCapture & { view: AssetPreviewView }>;
|
|
199
306
|
contactSheet: ViewportCapture & { width: number; height: number };
|
|
200
307
|
}
|
|
@@ -212,6 +319,13 @@ export interface StoryCaptureOptions {
|
|
|
212
319
|
* because a UI story is not the Asset Lab's square 3D view. */
|
|
213
320
|
width?: number;
|
|
214
321
|
height?: number;
|
|
322
|
+
/** Free capture camera for THREE stories (same contract as the Asset Lab's
|
|
323
|
+
* {@link AssetPreviewCameraChoice}). A selected story that renders on the
|
|
324
|
+
* DOM leg refuses these BY NAME rather than silently ignoring them. */
|
|
325
|
+
camera?: AssetPreviewCameraChoice;
|
|
326
|
+
/** Clip pose for THREE stories (same contract as the Asset Lab's
|
|
327
|
+
* {@link AssetPreviewPose}); DOM-leg stories refuse it by name. */
|
|
328
|
+
pose?: AssetPreviewPose;
|
|
215
329
|
}
|
|
216
330
|
|
|
217
331
|
export interface StoryVariantImage extends ViewportCapture {
|
|
@@ -313,11 +427,27 @@ export interface ShotSetPoseMorph {
|
|
|
313
427
|
influence: number;
|
|
314
428
|
}
|
|
315
429
|
|
|
316
|
-
/**
|
|
430
|
+
/** The TRANSLATION channel of a pose: a joint displaced along its own local
|
|
431
|
+
* axis. Rotations alone cannot state a gait's vertical truth — a crouch, a
|
|
432
|
+
* jump apex, the hip dip that makes a walk read as weighted — because those
|
|
433
|
+
* are the root/hips MOVING, not a joint bending (round-4 finding: shot sets
|
|
434
|
+
* could not photograph a gait). Same delta semantics as the rotation: the
|
|
435
|
+
* capture engine applies `bone.translateX/Y/Z(meters)`, composing onto
|
|
436
|
+
* whatever local position the GLB baked. */
|
|
437
|
+
export interface ShotSetPoseTranslation {
|
|
438
|
+
bone: string;
|
|
439
|
+
axis: 'x' | 'y' | 'z';
|
|
440
|
+
/** A DELTA along the bone's own local axis, in meters, relative to the
|
|
441
|
+
* loaded GLB's baked rest position. */
|
|
442
|
+
meters: number;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/** One step of a named pose. A flat union rather than parallel lists: a
|
|
317
446
|
* single expression is normally one rotation AND one morph (a jaw ROTATION
|
|
318
447
|
* plus a brow MORPH), so keeping them in one ordered list means a definition
|
|
319
|
-
* never has to zip them.
|
|
320
|
-
|
|
448
|
+
* never has to zip them. Discriminated by field name: `radians` is a
|
|
449
|
+
* rotation, `meters` a translation, `influence` a morph. */
|
|
450
|
+
export type ShotSetPoseStep = ShotSetPoseRotation | ShotSetPoseMorph | ShotSetPoseTranslation;
|
|
321
451
|
|
|
322
452
|
export type ShotSetShot =
|
|
323
453
|
| { label: string; view: 'turntable'; yaw: number; pose?: string | undefined }
|
|
@@ -717,7 +847,14 @@ export interface EditorState {
|
|
|
717
847
|
}
|
|
718
848
|
|
|
719
849
|
export type ViewPreset = 'top' | 'front' | 'right' | 'perspective';
|
|
720
|
-
export type ShadingMode =
|
|
850
|
+
export type ShadingMode =
|
|
851
|
+
| 'solid'
|
|
852
|
+
| 'clay'
|
|
853
|
+
| 'unlit'
|
|
854
|
+
| 'wireframe'
|
|
855
|
+
| 'matcap'
|
|
856
|
+
| 'normals'
|
|
857
|
+
| 'overdraw';
|
|
721
858
|
|
|
722
859
|
/** One operation on the active native animation document's recorder. */
|
|
723
860
|
export type AnimationCaptureAction = 'start' | 'stop' | 'review' | 'commit' | 'discard';
|
|
@@ -822,6 +959,9 @@ export type EditorViewDocument =
|
|
|
822
959
|
| { kind: 'asset'; path: string; entityId?: never; assetKind?: AssetKind }
|
|
823
960
|
| { kind: 'asset'; entityId: string; path?: never; assetKind?: 'model' }
|
|
824
961
|
| { kind: 'tool'; id: string }
|
|
962
|
+
/** A document the adapter's table lists (a model, a page) — `id` is the
|
|
963
|
+
* table entry's id — opened in the editor registered for its kind. */
|
|
964
|
+
| { kind: 'document'; id: string }
|
|
825
965
|
| { kind: 'world'; id: string }
|
|
826
966
|
| { kind: 'story'; modulePath: string; storyName: string; mode?: 'preview' | 'docs' }
|
|
827
967
|
| { kind: 'project-tool'; name: string }
|
|
@@ -829,6 +969,15 @@ export type EditorViewDocument =
|
|
|
829
969
|
| {
|
|
830
970
|
kind: 'workspace';
|
|
831
971
|
id: EditorViewWorkspaceDocumentId;
|
|
972
|
+
/**
|
|
973
|
+
* For a COMPONENT BOARD document: the portable story frame to open on
|
|
974
|
+
* — a story id, or a unique CSF export name or label (an ambiguous or
|
|
975
|
+
* unknown value refuses loudly, listing candidates). Emitted back by
|
|
976
|
+
* the board's own presentation so a captured view round-trips. This is
|
|
977
|
+
* the design ledger's "board story selector": without it only the
|
|
978
|
+
* derived default story could ever be addressed.
|
|
979
|
+
*/
|
|
980
|
+
story?: string;
|
|
832
981
|
};
|
|
833
982
|
|
|
834
983
|
export interface EditorView {
|
|
@@ -852,9 +1001,36 @@ export interface PresentedEditorView {
|
|
|
852
1001
|
warnings: string[];
|
|
853
1002
|
}
|
|
854
1003
|
|
|
1004
|
+
/**
|
|
1005
|
+
* How big a capture comes back.
|
|
1006
|
+
*
|
|
1007
|
+
* A NUMBER is a square of that size, and square stays the default — an
|
|
1008
|
+
* unstaged look at a model is a square question. `{width, height}` is for the
|
|
1009
|
+
* shaped answer: a video-aspect frame that needs no crop afterwards, which is
|
|
1010
|
+
* what the model/module lanes' looks are actually for.
|
|
1011
|
+
*
|
|
1012
|
+
* Both are bounded by the EDITOR's own ceiling — 64..1024 per side, plus a
|
|
1013
|
+
* total no larger than a 1024 square. That is the relay budget, not a taste:
|
|
1014
|
+
* the pixels cross the editor relay as base64 JSON, and 1024 is where even
|
|
1015
|
+
* incompressible RGBA still fits its 50 MB request limit (`asset-preview.ts`'s
|
|
1016
|
+
* `MIN_SIZE`/`MAX_SIZE`). For more picture, take more views, not bigger ones.
|
|
1017
|
+
*/
|
|
1018
|
+
export type CaptureDimensions = number | { readonly width: number; readonly height: number };
|
|
1019
|
+
|
|
855
1020
|
/** The pixels of the active center document, with enough provenance for an
|
|
856
1021
|
* agent to prove which user-visible subject it captured. Editor chrome is
|
|
857
1022
|
* deliberately excluded. */
|
|
1023
|
+
/** A photograph of the editor PAGE — every panel as the person sees it
|
|
1024
|
+
* (`capture-editor-chrome`; the door that lets a skin, a workspace or a
|
|
1025
|
+
* contributed panel be judged sighted through the product). */
|
|
1026
|
+
export interface EditorChromeCapture extends ViewportCapture {
|
|
1027
|
+
view: EditorView;
|
|
1028
|
+
/** The page's on-screen size in CSS pixels — the frame's own size. */
|
|
1029
|
+
size: { width: number; height: number };
|
|
1030
|
+
layers: { canvases: number; domOverlays: number };
|
|
1031
|
+
flatness?: { degenerate: boolean; warning?: string };
|
|
1032
|
+
}
|
|
1033
|
+
|
|
858
1034
|
export interface ActiveDocumentCapture extends ViewportCapture {
|
|
859
1035
|
document: {
|
|
860
1036
|
id: string;
|
|
@@ -921,8 +1097,9 @@ export type {
|
|
|
921
1097
|
export type InspectionSurface = 'three' | 'canvas' | 'dom' | 'asset-lab';
|
|
922
1098
|
|
|
923
1099
|
/** Which LAYOUT the one inspector box is in: the compact box over the
|
|
924
|
-
* viewport,
|
|
925
|
-
|
|
1100
|
+
* viewport, the same sections stacked in the dock column, or that column
|
|
1101
|
+
* with the sections tabbed behind a vertical rail (`properties`). */
|
|
1102
|
+
export type InspectionPresentationKind = 'card' | 'column' | 'properties';
|
|
926
1103
|
|
|
927
1104
|
/** One inspected field: a stable scriptable `path` and the value at it. */
|
|
928
1105
|
export interface InspectedField {
|
|
@@ -946,10 +1123,15 @@ export interface InspectedField {
|
|
|
946
1123
|
|
|
947
1124
|
/** A section's content. Custom RENDERING remains opaque — the wire never
|
|
948
1125
|
* introspects React — while any ordinary descriptor channel that chrome owns
|
|
949
|
-
*
|
|
950
|
-
*
|
|
951
|
-
*
|
|
952
|
-
*
|
|
1126
|
+
* IS a `fields` body here, including its write-refusal reasons: nothing is
|
|
1127
|
+
* rendered on this wire, so naming chrome a reader cannot see while hiding
|
|
1128
|
+
* the fields it can use is the wrong half. (Measured: the whole react/DOM
|
|
1129
|
+
* lane draws its own widgets over the style descriptors, so every one of its
|
|
1130
|
+
* sections reported `custom` and `inspect()` enumerated zero fields for a DOM
|
|
1131
|
+
* element.) The two opaque kinds are distinguished because "this subject has
|
|
1132
|
+
* a live preview" is a real fact about it: `custom` is a contributed block
|
|
1133
|
+
* with no descriptor channel of its own, `preview` is the subject's own
|
|
1134
|
+
* square view of itself.
|
|
953
1135
|
*
|
|
954
1136
|
* A custom body carries `data` when it can say what it DISPLAYS — the keys
|
|
955
1137
|
* are the section's own vocabulary, not a shared schema. The shipped case is
|
|
@@ -963,7 +1145,6 @@ export type InspectedSectionBody =
|
|
|
963
1145
|
id: string;
|
|
964
1146
|
title: string;
|
|
965
1147
|
data?: Record<string, unknown>;
|
|
966
|
-
fields?: readonly InspectedField[];
|
|
967
1148
|
}
|
|
968
1149
|
| { kind: 'preview'; id: string; title: string };
|
|
969
1150
|
|
|
@@ -1057,6 +1238,54 @@ export interface InspectedFieldWrite {
|
|
|
1057
1238
|
write: InspectedWriteDestination;
|
|
1058
1239
|
}
|
|
1059
1240
|
|
|
1241
|
+
/**
|
|
1242
|
+
* The STRUCTURE verbs — the hierarchy context menu's own ops, addressable.
|
|
1243
|
+
*
|
|
1244
|
+
* The names are the menu's, not the provider's, because the menu is the
|
|
1245
|
+
* surface a human uses and an agent is doing the same thing through a
|
|
1246
|
+
* different door (`delete` covers the provider's `remove`/`removeMany`: a
|
|
1247
|
+
* multi-id delete is ONE undoable op when the adapter can batch it).
|
|
1248
|
+
*/
|
|
1249
|
+
export type StructureOp =
|
|
1250
|
+
| 'create'
|
|
1251
|
+
| 'delete'
|
|
1252
|
+
| 'duplicate'
|
|
1253
|
+
| 'reparent'
|
|
1254
|
+
| 'reorder'
|
|
1255
|
+
| 'wrap'
|
|
1256
|
+
| 'unwrap'
|
|
1257
|
+
| 'group'
|
|
1258
|
+
| 'ungroup'
|
|
1259
|
+
| 'copy'
|
|
1260
|
+
| 'cut'
|
|
1261
|
+
| 'paste';
|
|
1262
|
+
|
|
1263
|
+
/** Arguments for one {@link StructureOp}. Everything is optional: `id`/`ids`
|
|
1264
|
+
* default to the current selection, the menu's own subject. */
|
|
1265
|
+
export interface StructureOpOptions {
|
|
1266
|
+
id?: string;
|
|
1267
|
+
ids?: readonly string[];
|
|
1268
|
+
/** `create`: which creatable kind (see the adapter's `creatableKinds`). */
|
|
1269
|
+
kind?: string;
|
|
1270
|
+
/** `create`/`reparent`/`paste`: the destination; `null`/absent = document root. */
|
|
1271
|
+
parentId?: string;
|
|
1272
|
+
/** `reorder`: move immediately before this sibling; absent = to the end. */
|
|
1273
|
+
beforeSiblingId?: string;
|
|
1274
|
+
/** `wrap`: the wrapper tag; absent = the adapter's own default. */
|
|
1275
|
+
tag?: string;
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
/** What one structure op answers. `write` is the same per-edit ack
|
|
1279
|
+
* `editor.setField()` carries — `persisted: false` means the tree moved and
|
|
1280
|
+
* no byte did. `id`/`ids` name what the op produced, when it produces one. */
|
|
1281
|
+
export interface StructureOpResult {
|
|
1282
|
+
id?: string | null;
|
|
1283
|
+
ids?: readonly string[];
|
|
1284
|
+
write?: InspectedWriteDestination;
|
|
1285
|
+
/** `copy` only: whether the clipboard actually took the payload. */
|
|
1286
|
+
copied?: boolean;
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1060
1289
|
// ---------------------------------------------------------------- hierarchy
|
|
1061
1290
|
//
|
|
1062
1291
|
// The wire mirror of the editor's own `SerializedHierarchyPanel`
|