@compilr-dev/sdk 0.29.7 → 0.30.0
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/canvas/index.d.ts +2 -0
- package/dist/canvas/index.js +7 -0
- package/dist/canvas/scene-ops.d.ts +122 -0
- package/dist/canvas/scene-ops.js +375 -0
- package/dist/canvas/scene.d.ts +207 -0
- package/dist/canvas/scene.js +843 -0
- package/dist/canvas/types.d.ts +9 -1
- package/dist/canvas/types.js +1 -0
- package/dist/capabilities/packs.d.ts +1 -1
- package/dist/capabilities/packs.js +30 -3
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -1
- package/dist/models/model-registry.js +44 -7
- package/dist/platform/context.d.ts +18 -1
- package/dist/platform/index.d.ts +4 -2
- package/dist/platform/index.js +4 -1
- package/dist/platform/scene-writer.d.ts +95 -0
- package/dist/platform/scene-writer.js +184 -0
- package/dist/platform/services.d.ts +20 -2
- package/dist/platform/tools/canvas-tools.js +101 -5
- package/dist/platform/tools/index.d.ts +1 -0
- package/dist/platform/tools/index.js +18 -2
- package/dist/platform/tools/scene-tools.d.ts +65 -0
- package/dist/platform/tools/scene-tools.js +452 -0
- package/dist/team/tool-config.js +21 -0
- package/package.json +2 -2
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 3D scene contract — the `scene` canvas type (3d-canvas-spec §2).
|
|
3
|
+
*
|
|
4
|
+
* A scene is VALIDATED JSON DATA, never code: a list of primitives in metres. Agents write
|
|
5
|
+
* it through the scene tools; the host draws it (three.js in Desktop's renderer). This module
|
|
6
|
+
* is the contract both sides bind to — types, limits, validation, normalisation and the few
|
|
7
|
+
* pieces of geometry (lift, bounds, fit) that must be ONE function everywhere.
|
|
8
|
+
*
|
|
9
|
+
* ⚠️ Renderer-safe on purpose: no imports at all. Desktop's renderer imports this through
|
|
10
|
+
* `@compilr-dev/sdk/canvas`; one node import here breaks its bundle (see
|
|
11
|
+
* `tests/canvas-subpath.test.ts`).
|
|
12
|
+
*/
|
|
13
|
+
export declare const SCENE_VERSION = 1;
|
|
14
|
+
export type Vec3 = [number, number, number];
|
|
15
|
+
export type Vec2 = [number, number];
|
|
16
|
+
export type SceneObjectType = 'box' | 'sphere' | 'cylinder' | 'cone' | 'torus' | 'extrude';
|
|
17
|
+
export declare const SCENE_OBJECT_TYPES: readonly SceneObjectType[];
|
|
18
|
+
export interface SceneMaterial {
|
|
19
|
+
/** 0..1, default 0.78 */
|
|
20
|
+
roughness?: number;
|
|
21
|
+
/** 0..1, default 0.02 */
|
|
22
|
+
metalness?: number;
|
|
23
|
+
/** 0.05..1, default 1 (transparent when < 1) */
|
|
24
|
+
opacity?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface SceneObjectBase {
|
|
27
|
+
/** Unique in the scene; /^[a-z0-9][a-z0-9_-]{0,47}$/ */
|
|
28
|
+
id: string;
|
|
29
|
+
/** Display name, ≤ 80 chars; the UI title-cases the id when absent. */
|
|
30
|
+
name?: string;
|
|
31
|
+
type: SceneObjectType;
|
|
32
|
+
/** Metres. y is the BOTTOM of the object: y = 0 sits on the floor (in the parent's frame). */
|
|
33
|
+
position: Vec3;
|
|
34
|
+
/** Degrees, Euler XYZ (three.js default order). Default [0, 0, 0]. */
|
|
35
|
+
rotation?: Vec3;
|
|
36
|
+
/** '#RRGGBB'. Filled by the writer from the neutral palette when absent. */
|
|
37
|
+
color?: string;
|
|
38
|
+
/** Parent object id — position/rotation are relative to the parent's frame. */
|
|
39
|
+
group?: string;
|
|
40
|
+
material?: SceneMaterial;
|
|
41
|
+
/** User-only lock: the inspector cannot move/remove it; agents still can (and are warned). */
|
|
42
|
+
locked?: boolean;
|
|
43
|
+
}
|
|
44
|
+
export interface BoxObject extends SceneObjectBase {
|
|
45
|
+
type: 'box';
|
|
46
|
+
/** w, h, d */
|
|
47
|
+
size: Vec3;
|
|
48
|
+
}
|
|
49
|
+
export interface SphereObject extends SceneObjectBase {
|
|
50
|
+
type: 'sphere';
|
|
51
|
+
radius: number;
|
|
52
|
+
}
|
|
53
|
+
export interface CylinderObject extends SceneObjectBase {
|
|
54
|
+
type: 'cylinder';
|
|
55
|
+
radius: number;
|
|
56
|
+
height: number;
|
|
57
|
+
}
|
|
58
|
+
export interface ConeObject extends SceneObjectBase {
|
|
59
|
+
type: 'cone';
|
|
60
|
+
radius: number;
|
|
61
|
+
height: number;
|
|
62
|
+
}
|
|
63
|
+
/** Lies flat (ring in the x–z plane). radius = ring radius, tube = tube radius. */
|
|
64
|
+
export interface TorusObject extends SceneObjectBase {
|
|
65
|
+
type: 'torus';
|
|
66
|
+
radius: number;
|
|
67
|
+
tube: number;
|
|
68
|
+
}
|
|
69
|
+
/** An outline in plan (x, z), local to position, extruded upward by `height`. Walls and floors. */
|
|
70
|
+
export interface ExtrudeObject extends SceneObjectBase {
|
|
71
|
+
type: 'extrude';
|
|
72
|
+
points: Vec2[];
|
|
73
|
+
height: number;
|
|
74
|
+
}
|
|
75
|
+
export type SceneObject = BoxObject | SphereObject | CylinderObject | ConeObject | TorusObject | ExtrudeObject;
|
|
76
|
+
export interface SceneCamera {
|
|
77
|
+
position: Vec3;
|
|
78
|
+
target: Vec3;
|
|
79
|
+
}
|
|
80
|
+
export type SceneLight = {
|
|
81
|
+
type: 'sun';
|
|
82
|
+
position: Vec3;
|
|
83
|
+
intensity?: number;
|
|
84
|
+
castShadow?: boolean;
|
|
85
|
+
} | {
|
|
86
|
+
type: 'ambient';
|
|
87
|
+
intensity?: number;
|
|
88
|
+
};
|
|
89
|
+
export interface SceneFile {
|
|
90
|
+
version: 1;
|
|
91
|
+
name: string;
|
|
92
|
+
/** Only metres in v1. */
|
|
93
|
+
units: 'm';
|
|
94
|
+
/** Missing → the viewer fits the camera to the objects. */
|
|
95
|
+
camera?: SceneCamera;
|
|
96
|
+
/** Missing → the default studio light. */
|
|
97
|
+
lights?: SceneLight[];
|
|
98
|
+
objects: SceneObject[];
|
|
99
|
+
}
|
|
100
|
+
export interface SceneBounds {
|
|
101
|
+
min: Vec3;
|
|
102
|
+
max: Vec3;
|
|
103
|
+
}
|
|
104
|
+
export declare const SCENE_MAX_OBJECTS = 500;
|
|
105
|
+
export declare const SCENE_MAX_BYTES: number;
|
|
106
|
+
/** Max objects in one scene_add_object batch (Q-1). */
|
|
107
|
+
export declare const SCENE_MAX_BATCH = 50;
|
|
108
|
+
export declare const SCENE_MAX_COORD = 1000;
|
|
109
|
+
export declare const SCENE_SIZE_MIN = 0.01;
|
|
110
|
+
export declare const SCENE_SIZE_MAX = 500;
|
|
111
|
+
export declare const SCENE_RADIUS_MIN = 0.01;
|
|
112
|
+
export declare const SCENE_RADIUS_MAX = 250;
|
|
113
|
+
export declare const SCENE_TUBE_MIN = 0.005;
|
|
114
|
+
export declare const SCENE_POINTS_MIN = 3;
|
|
115
|
+
export declare const SCENE_POINTS_MAX = 256;
|
|
116
|
+
export declare const SCENE_MAX_LIGHTS = 4;
|
|
117
|
+
export declare const SCENE_MAX_SHADOW_LIGHTS = 2;
|
|
118
|
+
export declare const SCENE_LIGHT_INTENSITY_MAX = 10;
|
|
119
|
+
export declare const SCENE_MAX_GROUP_DEPTH = 8;
|
|
120
|
+
export declare const SCENE_NAME_MAX = 80;
|
|
121
|
+
export declare const SCENE_OPACITY_MIN = 0.05;
|
|
122
|
+
export declare const SCENE_ID_PATTERN: RegExp;
|
|
123
|
+
/** Object colours never read as state (README) — a neutral palette, filled by insertion index. */
|
|
124
|
+
export declare const SCENE_NEUTRAL_PALETTE: readonly string[];
|
|
125
|
+
/** Accessible names for the palette swatches, same order (Q-10). */
|
|
126
|
+
export declare const SCENE_PALETTE_NAMES: readonly string[];
|
|
127
|
+
export declare const SCENE_DEFAULT_MATERIAL: Readonly<Required<SceneMaterial>>;
|
|
128
|
+
/** The reference camera, used for an empty scene. */
|
|
129
|
+
export declare const SCENE_DEFAULT_CAMERA: Readonly<SceneCamera>;
|
|
130
|
+
/** Vertical field of view of the viewer camera, degrees. */
|
|
131
|
+
export declare const SCENE_CAMERA_FOV = 38;
|
|
132
|
+
/** A new, empty scene. */
|
|
133
|
+
export declare function emptyScene(name: string): SceneFile;
|
|
134
|
+
/**
|
|
135
|
+
* Defaults for a freshly added shape of each type (the reference's fallbacks), for the
|
|
136
|
+
* inspector's "Add a shape" menu. Position is the origin.
|
|
137
|
+
*/
|
|
138
|
+
export declare function defaultObjectFor(type: SceneObjectType, id: string): SceneObject;
|
|
139
|
+
/** The stored form: pretty-printed, because agents read and cite it (§4.1). */
|
|
140
|
+
export declare function serializeScene(scene: SceneFile): string;
|
|
141
|
+
/** `slug(title).scene.json` — the display file name and the JSON export's default name. */
|
|
142
|
+
export declare function sceneFileName(title: string): string;
|
|
143
|
+
/** UTF-8 byte length without TextEncoder (keeps this module free of DOM/node typings). */
|
|
144
|
+
export declare function utf8Bytes(s: string): number;
|
|
145
|
+
export type SceneValidationResult = {
|
|
146
|
+
ok: true;
|
|
147
|
+
scene: SceneFile;
|
|
148
|
+
} | {
|
|
149
|
+
ok: false;
|
|
150
|
+
errors: string[];
|
|
151
|
+
};
|
|
152
|
+
/** Short, stable number rendering for messages and summaries. */
|
|
153
|
+
export declare function fmtNum(n: number): string;
|
|
154
|
+
export declare function fmtVec(v: readonly number[]): string;
|
|
155
|
+
/** Drop a closing duplicate of the first point (§2.3: dropped, not rejected). */
|
|
156
|
+
export declare function openOutline(points: Vec2[]): Vec2[];
|
|
157
|
+
/**
|
|
158
|
+
* Is the (open) outline a simple polygon? O(n²) segment test — ExtrudeGeometry's
|
|
159
|
+
* triangulation silently breaks on self-intersection. Returns the first offending edge pair.
|
|
160
|
+
*/
|
|
161
|
+
export declare function findSelfIntersection(points: Vec2[]): [number, number] | null;
|
|
162
|
+
/**
|
|
163
|
+
* Validate an untrusted scene (agent JSON, a stored row, an import). Every error names the
|
|
164
|
+
* field path and what is allowed. On success the returned scene is a deep copy of the input
|
|
165
|
+
* (not yet normalised — see `normalizeScene`).
|
|
166
|
+
*/
|
|
167
|
+
export declare function validateScene(input: unknown): SceneValidationResult;
|
|
168
|
+
/** '#abc' / '#aabbcc' → '#AABBCC'. Assumes a valid hex (validated first). */
|
|
169
|
+
export declare function normalizeColor(hex: string): string;
|
|
170
|
+
/** Degrees → (−180, 180]. */
|
|
171
|
+
export declare function normalizeAngle(deg: number): number;
|
|
172
|
+
/**
|
|
173
|
+
* Fill what the writer owns: upper-case #RRGGBB colours, the neutral default colour by
|
|
174
|
+
* insertion index (so the stored file is explicit and agent-readable), rotations wrapped to
|
|
175
|
+
* (−180, 180], closing duplicate points dropped. Never fills camera/lights — their absence
|
|
176
|
+
* means "fit" / "studio light". Pure; returns a new scene.
|
|
177
|
+
*/
|
|
178
|
+
export declare function normalizeScene(scene: SceneFile): SceneFile;
|
|
179
|
+
/**
|
|
180
|
+
* Half-height from the object's BOTTOM (its `position.y`) to its geometric centre, where the
|
|
181
|
+
* mesh sits. extrude is 0: its geometry already starts at the floor. ONE function — the
|
|
182
|
+
* viewer, the fit and the GLB export must agree.
|
|
183
|
+
*/
|
|
184
|
+
export declare function liftFor(obj: SceneObject): number;
|
|
185
|
+
/**
|
|
186
|
+
* World matrix of each object's mesh (row-major 4×4), keyed by id, with group parenting
|
|
187
|
+
* applied. Assumes a validated scene (no cycles).
|
|
188
|
+
*/
|
|
189
|
+
export declare function sceneWorldMatrices(scene: SceneFile): Map<string, number[]>;
|
|
190
|
+
/** World-space AABB of all objects (conservative for rotated shapes). null when empty. */
|
|
191
|
+
export declare function sceneBounds(scene: SceneFile): SceneBounds | null;
|
|
192
|
+
/** The reference view direction ([7, 5.5, 8], normalised). */
|
|
193
|
+
export declare const SCENE_CAMERA_DIRECTION: Readonly<Vec3>;
|
|
194
|
+
/**
|
|
195
|
+
* The camera used when a scene has none: look at the bounds' centre from the reference
|
|
196
|
+
* direction, at the distance that fits the bounding sphere in the vertical FOV, × 1.2.
|
|
197
|
+
* null bounds (empty scene) → the reference default.
|
|
198
|
+
*/
|
|
199
|
+
export declare function fitCamera(bounds: SceneBounds | null, fovDeg?: number): SceneCamera;
|
|
200
|
+
/** The camera to view a scene with: its own, or the fit. */
|
|
201
|
+
export declare function sceneCamera(scene: SceneFile): SceneCamera;
|
|
202
|
+
/** One line: "12 objects, bounds 6.2 × 4 × 2.7 m" (W × D × H). */
|
|
203
|
+
export declare function describeScene(scene: SceneFile): string;
|
|
204
|
+
/** The ids of an object's descendants (children, grandchildren, …), in scene order. */
|
|
205
|
+
export declare function descendantsOf(scene: SceneFile, id: string): string[];
|
|
206
|
+
/** Turn a display name (or type) into an id candidate: lowercase slug, ≤ 48 chars. */
|
|
207
|
+
export declare function slugifySceneId(text: string): string;
|