@vgai/editor-sdk 0.5.42 → 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/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. */
@@ -204,16 +247,61 @@ export type AssetPreviewSource =
204
247
  */
205
248
  export type AssetPreviewStage = 'lab' | 'scene';
206
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
+
207
277
  export interface AssetPreviewOptions {
208
278
  width?: number;
209
279
  height?: number;
210
280
  background?: AssetPreviewBackground;
211
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;
212
298
  }
213
299
 
214
300
  export interface AssetPreviewCapture {
215
301
  width: number;
216
302
  height: number;
303
+ /** Absent from editors that predate orientation reporting. */
304
+ orientation?: AssetPreviewOrientation;
217
305
  views: Array<ViewportCapture & { view: AssetPreviewView }>;
218
306
  contactSheet: ViewportCapture & { width: number; height: number };
219
307
  }
@@ -231,6 +319,13 @@ export interface StoryCaptureOptions {
231
319
  * because a UI story is not the Asset Lab's square 3D view. */
232
320
  width?: number;
233
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;
234
329
  }
235
330
 
236
331
  export interface StoryVariantImage extends ViewportCapture {
@@ -332,11 +427,27 @@ export interface ShotSetPoseMorph {
332
427
  influence: number;
333
428
  }
334
429
 
335
- /** One step of a named pose. A flat union rather than two parallel lists: a
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
336
446
  * single expression is normally one rotation AND one morph (a jaw ROTATION
337
447
  * plus a brow MORPH), so keeping them in one ordered list means a definition
338
- * never has to zip them. */
339
- export type ShotSetPoseStep = ShotSetPoseRotation | ShotSetPoseMorph;
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;
340
451
 
341
452
  export type ShotSetShot =
342
453
  | { label: string; view: 'turntable'; yaw: number; pose?: string | undefined }
@@ -736,7 +847,14 @@ export interface EditorState {
736
847
  }
737
848
 
738
849
  export type ViewPreset = 'top' | 'front' | 'right' | 'perspective';
739
- export type ShadingMode = 'solid' | 'clay' | 'unlit' | 'wireframe' | 'normals' | 'overdraw';
850
+ export type ShadingMode =
851
+ | 'solid'
852
+ | 'clay'
853
+ | 'unlit'
854
+ | 'wireframe'
855
+ | 'matcap'
856
+ | 'normals'
857
+ | 'overdraw';
740
858
 
741
859
  /** One operation on the active native animation document's recorder. */
742
860
  export type AnimationCaptureAction = 'start' | 'stop' | 'review' | 'commit' | 'discard';
@@ -841,6 +959,9 @@ export type EditorViewDocument =
841
959
  | { kind: 'asset'; path: string; entityId?: never; assetKind?: AssetKind }
842
960
  | { kind: 'asset'; entityId: string; path?: never; assetKind?: 'model' }
843
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 }
844
965
  | { kind: 'world'; id: string }
845
966
  | { kind: 'story'; modulePath: string; storyName: string; mode?: 'preview' | 'docs' }
846
967
  | { kind: 'project-tool'; name: string }
@@ -848,6 +969,15 @@ export type EditorViewDocument =
848
969
  | {
849
970
  kind: 'workspace';
850
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;
851
981
  };
852
982
 
853
983
  export interface EditorView {
@@ -871,9 +1001,36 @@ export interface PresentedEditorView {
871
1001
  warnings: string[];
872
1002
  }
873
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
+
874
1020
  /** The pixels of the active center document, with enough provenance for an
875
1021
  * agent to prove which user-visible subject it captured. Editor chrome is
876
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
+
877
1034
  export interface ActiveDocumentCapture extends ViewportCapture {
878
1035
  document: {
879
1036
  id: string;
@@ -940,8 +1097,9 @@ export type {
940
1097
  export type InspectionSurface = 'three' | 'canvas' | 'dom' | 'asset-lab';
941
1098
 
942
1099
  /** Which LAYOUT the one inspector box is in: the compact box over the
943
- * viewport, or the same sections stacked in the dock column. */
944
- export type InspectionPresentationKind = 'card' | 'column';
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';
945
1103
 
946
1104
  /** One inspected field: a stable scriptable `path` and the value at it. */
947
1105
  export interface InspectedField {
@@ -965,10 +1123,15 @@ export interface InspectedField {
965
1123
 
966
1124
  /** A section's content. Custom RENDERING remains opaque — the wire never
967
1125
  * introspects React — while any ordinary descriptor channel that chrome owns
968
- * remains visible as `fields`, including its write-refusal reasons. The two
969
- * opaque kinds are distinguished because "this subject has a live preview"
970
- * is a real fact about it: `custom` is a contributed block, `preview` is the
971
- * subject's own square view of itself.
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.
972
1135
  *
973
1136
  * A custom body carries `data` when it can say what it DISPLAYS — the keys
974
1137
  * are the section's own vocabulary, not a shared schema. The shipped case is
@@ -982,7 +1145,6 @@ export type InspectedSectionBody =
982
1145
  id: string;
983
1146
  title: string;
984
1147
  data?: Record<string, unknown>;
985
- fields?: readonly InspectedField[];
986
1148
  }
987
1149
  | { kind: 'preview'; id: string; title: string };
988
1150
 
@@ -1076,6 +1238,54 @@ export interface InspectedFieldWrite {
1076
1238
  write: InspectedWriteDestination;
1077
1239
  }
1078
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
+
1079
1289
  // ---------------------------------------------------------------- hierarchy
1080
1290
  //
1081
1291
  // The wire mirror of the editor's own `SerializedHierarchyPanel`