@volter/editor-threejs 0.5.211 → 0.5.212
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/NOTICE +7 -2
- package/README.md +8 -13
- package/contributions/animation-mixers.service.ts +2 -4
- package/contributions/animation-timeline.utility.tsx +1 -2
- package/contributions/three.page.ts +50 -0
- package/dist-node/serving.mjs +84 -3
- package/dist-node/shared-three.mjs +145 -0
- package/package.json +296 -16
- package/serving/animation-stamp.ts +1 -1
- package/serving/index.ts +22 -5
- package/serving/model-import-conversion.ts +6 -3
- package/serving/shared-three.ts +176 -0
- package/src/adapter/constraint.ts +1 -18
- package/src/adapter/object3d-authoring-subject.ts +1 -12
- package/src/adapter/reflection-probe.ts +1 -9
- package/src/adapter/three-contract.ts +6 -60
- package/src/animation/live-mixers.ts +0 -4
- package/src/api.ts +7 -0
- package/src/asset-loaders.ts +2 -178
- package/src/capture/photograph-sampling.ts +333 -0
- package/src/capture/scene.ts +1 -1
- package/src/ecs/object-marks.ts +6 -14
- package/src/ecs/user-data.ts +3 -138
- package/src/kit/animation/three-clips-subject.ts +19 -42
- package/src/kit/asset-compare-core.ts +161 -0
- package/src/kit/asset-compare.ts +8 -27
- package/src/kit/asset-preview-command.ts +14 -19
- package/src/kit/asset-preview-framing.ts +8 -67
- package/src/kit/asset-preview.ts +109 -342
- package/src/kit/asset-workflow/model-inspection.ts +11 -154
- package/src/kit/asset-workflow/preview-resource-lifetime.ts +25 -0
- package/src/kit/authoring/component-instance-root.ts +3 -39
- package/src/kit/authoring/live-object-transform.ts +1 -30
- package/src/kit/authoring/object3d-document-session-registry.ts +7 -15
- package/src/kit/authoring/object3d-document-session.ts +471 -208
- package/src/kit/authoring/shell-viewport-policy.ts +18 -24
- package/src/kit/authoring/source-object3d-authoring-adapter.ts +6 -48
- package/src/kit/authoring/three-projection-core.ts +11 -40
- package/src/kit/authoring/viewport-pick-context.ts +5 -12
- package/src/kit/authoring/viewport-raycast.ts +15 -93
- package/src/kit/authoring/world-hidden-viewport.ts +8 -61
- package/src/kit/capture-camera-pose.ts +68 -0
- package/src/kit/collaboration-presence.ts +41 -0
- package/src/kit/components/CameraInfo.tsx +4 -6
- package/src/kit/components/InspectorObjectPreview.tsx +3 -30
- package/src/kit/components/Object3DDocumentToolbar.css +75 -0
- package/src/kit/components/Object3DDocumentToolbar.tsx +18 -84
- package/src/kit/components/Object3DDocumentViewport.tsx +5 -8
- package/src/kit/components/StageHost.css +40 -0
- package/src/kit/components/StageHost.tsx +181 -404
- package/src/kit/components/StageOverlays.tsx +1 -2
- package/src/kit/components/StatsOverlay.tsx +5 -17
- package/src/kit/components/ViewportFurniture.tsx +27 -154
- package/src/kit/components/ViewportOverlay.tsx +13 -17
- package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
- package/src/kit/components/ViewportShadingMenu.tsx +2 -42
- package/src/kit/components/ViewportViewMenu.tsx +7 -18
- package/src/kit/components/asset-viewers/EntityModelDocument.tsx +4 -13
- package/src/kit/components/asset-viewers/EnvironmentAssetDocument.tsx +5 -5
- package/src/kit/components/asset-viewers/LiveModuleDocument.tsx +24 -102
- package/src/kit/components/asset-viewers/LutAssetDocument.tsx +6 -6
- package/src/kit/components/asset-viewers/Object3DPreview.tsx +10 -45
- package/src/kit/components/asset-viewers/QuarksAssetDocument.tsx +2 -2
- package/src/kit/components/asset-viewers/ShaderAssetDocument.tsx +11 -10
- package/src/kit/components/asset-viewers/shader-source.ts +144 -0
- package/src/kit/components/asset-viewers/three-asset-viewers.tsx +2 -14
- package/src/kit/components/object3d-contribution-surfaces.tsx +1 -1
- package/src/kit/components/stage-keyboard.tsx +6 -12
- package/src/kit/components/stage-overlay-set.tsx +11 -20
- package/src/kit/components/stage-presence-markers.ts +9 -32
- package/src/kit/components/stage-transform-chrome.ts +4 -4
- package/src/kit/components/stage-transform-tools.tsx +7 -14
- package/src/kit/components/standard-viewport-dressing.ts +47 -167
- package/src/kit/components/world-root-binding.ts +2 -7
- package/src/kit/constraint-helper.ts +1 -1
- package/src/kit/document-renderer-session.ts +114 -0
- package/src/kit/editor-presentation-activity.ts +58 -0
- package/src/kit/editor-shell-store.ts +31 -403
- package/src/kit/editor-viewport.ts +476 -1762
- package/src/kit/entity-lod.ts +3 -16
- package/src/kit/entity-object.ts +1 -39
- package/src/kit/hierarchy-mark-reader.ts +13 -30
- package/src/kit/instanced-presentation.ts +1 -47
- package/src/kit/live-gesture-lock.ts +35 -0
- package/src/kit/live-module-source.ts +12 -52
- package/src/kit/model-thumbnail.ts +7 -35
- package/src/kit/play-camera-flight.ts +7 -16
- package/src/kit/projection/three.ts +13 -366
- package/src/kit/retained-document-states.ts +91 -0
- package/src/kit/scene-document-viewport.ts +3 -3
- package/src/kit/scene-framing.ts +11 -152
- package/src/kit/scene-view-fog.ts +2 -47
- package/src/kit/spatial-handle-visuals.ts +19 -28
- package/src/kit/stories/three-story-model.ts +5 -33
- package/src/kit/three-canvas-render.ts +3 -4
- package/src/kit/three-hierarchy-row-media.ts +3 -11
- package/src/kit/three-inspection-media.ts +6 -6
- package/src/kit/three-integration.ts +18 -18
- package/src/kit/three-state.ts +2 -19
- package/src/kit/three-viewport/camera-fit.ts +2 -6
- package/src/kit/three-viewport/selection-brackets.ts +5 -20
- package/src/kit/three-viewport/selection-outline.ts +4 -56
- package/src/kit/three-viewport/skeleton-helper.ts +1 -32
- package/src/kit/three-viewport/source-color.ts +1 -33
- package/src/kit/three-viewport/studio-environment.ts +4 -55
- package/src/kit/three-viewport-presentation.ts +23 -0
- package/src/kit/transport-strip.tsx +147 -0
- package/src/kit/viewport-actions.ts +8 -50
- package/src/kit/viewport-authoring-policy.ts +5 -52
- package/src/kit/viewport-commands.ts +28 -57
- package/src/kit/viewport-hotkeys.ts +29 -31
- package/src/kit/viewport-status-facet.ts +4 -5
- package/src/kit/viewport-surface-status.tsx +44 -0
- package/src/loader.ts +8 -71
- package/src/object3d-contributions.ts +18 -34
- package/src/viewport/clip-planes.ts +4 -32
- package/src/viewport/content-bounds.ts +13 -142
- package/src/viewport/editor-layers.ts +4 -26
- package/src/viewport/environment.ts +1 -1
- package/src/viewport/preview-renderer.ts +7 -45
- package/src/viewport/renderer-ownership.ts +14 -62
- package/src/viewport-api.ts +14 -33
- package/src/viewport-door.ts +16 -86
- package/contributions/three-integration.service.ts +0 -13
- package/src/adapter/hierarchy-marks.ts +0 -156
- package/src/adapter/ingest/scene-capture.ts +0 -843
- package/src/adapter/ingest/structural-ids.ts +0 -139
- package/src/adapter/ingest/visible-capture-window.ts +0 -302
- package/src/adapter/renderer-config.ts +0 -115
- package/src/asset-parse-error.ts +0 -29
- package/src/host-hierarchy-objects.ts +0 -31
- package/src/kit/authoring/design-time-settle.ts +0 -343
- package/src/kit/camera-authoring.ts +0 -175
|
@@ -98,41 +98,6 @@ export function classifyModelStructure(
|
|
|
98
98
|
return 'static';
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
export interface Object3DNodeInspection {
|
|
102
|
-
readonly type: string;
|
|
103
|
-
readonly visible: boolean;
|
|
104
|
-
readonly children: number;
|
|
105
|
-
readonly descendants: number;
|
|
106
|
-
readonly renderOrder: number;
|
|
107
|
-
readonly layers: number;
|
|
108
|
-
readonly geometry: null | {
|
|
109
|
-
readonly vertices: number;
|
|
110
|
-
readonly triangles: number;
|
|
111
|
-
readonly indexed: boolean;
|
|
112
|
-
readonly attributes: readonly string[];
|
|
113
|
-
readonly uvChannels: readonly string[];
|
|
114
|
-
readonly morphTargets: number;
|
|
115
|
-
readonly nonFiniteAttributeValues: number;
|
|
116
|
-
readonly bounds: { x: number; y: number; z: number } | null;
|
|
117
|
-
};
|
|
118
|
-
readonly materials: Array<{
|
|
119
|
-
readonly id: string;
|
|
120
|
-
readonly name: string;
|
|
121
|
-
readonly type: string;
|
|
122
|
-
readonly color: string | null;
|
|
123
|
-
readonly textureSlots: readonly string[];
|
|
124
|
-
}>;
|
|
125
|
-
readonly skin: null | {
|
|
126
|
-
readonly bones: number;
|
|
127
|
-
readonly rootBones: readonly string[];
|
|
128
|
-
readonly bindMode: string;
|
|
129
|
-
};
|
|
130
|
-
readonly bone: null | {
|
|
131
|
-
readonly parent: string | null;
|
|
132
|
-
readonly children: readonly string[];
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
101
|
interface SkinWeightInspection {
|
|
137
102
|
readonly weightedVertices: number;
|
|
138
103
|
readonly nonNormalizedVertices: number;
|
|
@@ -155,16 +120,14 @@ const textureKeys = [
|
|
|
155
120
|
'specularMap',
|
|
156
121
|
] as const;
|
|
157
122
|
|
|
158
|
-
/**
|
|
159
|
-
*
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
* same reason as `../authoring/three-scene-identity.ts`.
|
|
167
|
-
*/
|
|
123
|
+
/** The URL a texture's image was loaded from, when it has one (an HTMLImageElement's `src`); r186
|
|
124
|
+
* types a texture's source data by its image parameter, unknown here. */
|
|
125
|
+
function sourceUrl(texture: THREE.Texture): string | undefined {
|
|
126
|
+
const data = texture.source.data as { src?: unknown } | null | undefined;
|
|
127
|
+
return typeof data?.src === 'string' ? data.src : undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Read a material’s base color as hex, or null when absent. The isColor brand supports other realms. */
|
|
168
131
|
function materialColorHex(material: THREE.Material): string | null {
|
|
169
132
|
if (!('color' in material)) return null;
|
|
170
133
|
const color = (material as THREE.Material & { color?: THREE.Color }).color;
|
|
@@ -354,10 +317,7 @@ export function inspectModel(root: THREE.Object3D): ModelInspection {
|
|
|
354
317
|
materialUsers.set(material, users);
|
|
355
318
|
const slots = materialSlots.get(material) ?? [];
|
|
356
319
|
for (const key of textureKeys) {
|
|
357
|
-
//
|
|
358
|
-
// `source-object3d-authoring-adapter.ts` and the selection inspector,
|
|
359
|
-
// so under the packaged runtime the material was built by the
|
|
360
|
-
// PROJECT's `three`. See `../authoring/three-scene-identity.ts`.
|
|
320
|
+
// Use the structural material brand for objects supplied by project modules.
|
|
361
321
|
const texture = (material as THREE.Material & Record<string, unknown>)[key] as
|
|
362
322
|
| THREE.Texture
|
|
363
323
|
| undefined;
|
|
@@ -374,7 +334,7 @@ export function inspectModel(root: THREE.Object3D): ModelInspection {
|
|
|
374
334
|
materialId: material.uuid,
|
|
375
335
|
materialName: material.name || material.type,
|
|
376
336
|
slot: key,
|
|
377
|
-
textureName: texture.name || texture
|
|
337
|
+
textureName: texture.name || sourceUrl(texture) || 'Texture',
|
|
378
338
|
width: image?.width ?? null,
|
|
379
339
|
height: image?.height ?? null,
|
|
380
340
|
format: texture.format,
|
|
@@ -438,7 +398,7 @@ export function inspectModel(root: THREE.Object3D): ModelInspection {
|
|
|
438
398
|
hierarchy,
|
|
439
399
|
materialNames: [...materials].map((material) => material.name || material.type),
|
|
440
400
|
textureNames: [...textures].map(
|
|
441
|
-
(texture) => texture.name || texture
|
|
401
|
+
(texture) => texture.name || sourceUrl(texture) || 'Texture',
|
|
442
402
|
),
|
|
443
403
|
materialSlots: [...materials].map((material) => ({
|
|
444
404
|
id: material.uuid,
|
|
@@ -600,87 +560,6 @@ export function inspectModelRig(root: THREE.Object3D): ModelRigInspection {
|
|
|
600
560
|
};
|
|
601
561
|
}
|
|
602
562
|
|
|
603
|
-
function inspectNodeGeometry(geometry: THREE.BufferGeometry | undefined) {
|
|
604
|
-
if (!geometry) return null;
|
|
605
|
-
const size = geometryBounds(geometry)?.getSize(new THREE.Vector3());
|
|
606
|
-
const position = geometry.getAttribute('position');
|
|
607
|
-
return {
|
|
608
|
-
vertices: position?.count ?? 0,
|
|
609
|
-
triangles: Math.floor((geometry.index?.count ?? position?.count ?? 0) / 3),
|
|
610
|
-
indexed: geometry.index !== null,
|
|
611
|
-
attributes: Object.keys(geometry.attributes).sort(),
|
|
612
|
-
uvChannels: Object.keys(geometry.attributes)
|
|
613
|
-
.filter((name) => /^uv\d*$/.test(name))
|
|
614
|
-
.sort(),
|
|
615
|
-
morphTargets: geometry.morphAttributes['position']?.length ?? 0,
|
|
616
|
-
nonFiniteAttributeValues: countNonFiniteAttributeValues(geometry),
|
|
617
|
-
bounds: size ? { x: size.x, y: size.y, z: size.z } : null,
|
|
618
|
-
} satisfies NonNullable<Object3DNodeInspection['geometry']>;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
function inspectNodeMaterials(mesh: THREE.Mesh): Object3DNodeInspection['materials'] {
|
|
622
|
-
const objectMaterials = Array.isArray(mesh.material)
|
|
623
|
-
? mesh.material
|
|
624
|
-
: mesh.material
|
|
625
|
-
? [mesh.material]
|
|
626
|
-
: [];
|
|
627
|
-
return objectMaterials.map((material) => ({
|
|
628
|
-
id: material.uuid,
|
|
629
|
-
name: material.name || material.type,
|
|
630
|
-
type: material.type,
|
|
631
|
-
color: materialColorHex(material),
|
|
632
|
-
textureSlots: textureKeys.filter(
|
|
633
|
-
(key) =>
|
|
634
|
-
((material as THREE.Material & Record<string, unknown>)[key] as THREE.Texture | undefined)
|
|
635
|
-
?.isTexture === true,
|
|
636
|
-
),
|
|
637
|
-
}));
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
function inspectNodeSkin(object: THREE.Object3D): Object3DNodeInspection['skin'] {
|
|
641
|
-
const mesh = object as THREE.SkinnedMesh;
|
|
642
|
-
if (!mesh.isSkinnedMesh) return null;
|
|
643
|
-
return {
|
|
644
|
-
bones: mesh.skeleton.bones.length,
|
|
645
|
-
rootBones: mesh.skeleton.bones
|
|
646
|
-
.filter((bone) => !(bone.parent as THREE.Bone | null)?.isBone)
|
|
647
|
-
.map((bone) => bone.name || bone.uuid),
|
|
648
|
-
bindMode: mesh.bindMode,
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
function inspectNodeBone(object: THREE.Object3D): Object3DNodeInspection['bone'] {
|
|
653
|
-
const bone = object as THREE.Bone;
|
|
654
|
-
if (!bone.isBone) return null;
|
|
655
|
-
return {
|
|
656
|
-
parent: (bone.parent as THREE.Bone | null)?.isBone
|
|
657
|
-
? bone.parent?.name || bone.parent?.uuid || null
|
|
658
|
-
: null,
|
|
659
|
-
children: bone.children
|
|
660
|
-
.filter((child): child is THREE.Bone => (child as THREE.Bone).isBone)
|
|
661
|
-
.map((child) => child.name || child.uuid),
|
|
662
|
-
};
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
/** Inspect one selected native node without manufacturing an authored descriptor. */
|
|
666
|
-
export function inspectObject3DNode(object: THREE.Object3D): Object3DNodeInspection {
|
|
667
|
-
let descendants = -1;
|
|
668
|
-
object.traverse(() => descendants++);
|
|
669
|
-
const mesh = object as THREE.Mesh;
|
|
670
|
-
return {
|
|
671
|
-
type: object.type,
|
|
672
|
-
visible: object.visible,
|
|
673
|
-
children: object.children.length,
|
|
674
|
-
descendants,
|
|
675
|
-
renderOrder: object.renderOrder,
|
|
676
|
-
layers: object.layers.mask,
|
|
677
|
-
geometry: inspectNodeGeometry(mesh.geometry),
|
|
678
|
-
materials: inspectNodeMaterials(mesh),
|
|
679
|
-
skin: inspectNodeSkin(object),
|
|
680
|
-
bone: inspectNodeBone(object),
|
|
681
|
-
};
|
|
682
|
-
}
|
|
683
|
-
|
|
684
563
|
export type ModelDiagnosticMode =
|
|
685
564
|
| 'lit'
|
|
686
565
|
| 'unlit'
|
|
@@ -806,25 +685,3 @@ export function rootMotionTrailPoints(clip: THREE.AnimationClip): THREE.Vector3[
|
|
|
806
685
|
}
|
|
807
686
|
return points;
|
|
808
687
|
}
|
|
809
|
-
|
|
810
|
-
/** Resolve a hierarchy/material row to the preview objects it represents. */
|
|
811
|
-
export function modelSelectionObjects(
|
|
812
|
-
root: THREE.Object3D,
|
|
813
|
-
selection: { kind: 'node' | 'material'; id: string },
|
|
814
|
-
): THREE.Object3D[] {
|
|
815
|
-
if (selection.kind === 'node') {
|
|
816
|
-
const object = root.getObjectByProperty('uuid', selection.id);
|
|
817
|
-
return object ? [object] : [];
|
|
818
|
-
}
|
|
819
|
-
const selected: THREE.Object3D[] = [];
|
|
820
|
-
root.traverse((object) => {
|
|
821
|
-
const mesh = object as THREE.Mesh;
|
|
822
|
-
const materials = Array.isArray(mesh.material)
|
|
823
|
-
? mesh.material
|
|
824
|
-
: mesh.material
|
|
825
|
-
? [mesh.material]
|
|
826
|
-
: [];
|
|
827
|
-
if (materials.some((material) => material.uuid === selection.id)) selected.push(mesh);
|
|
828
|
-
});
|
|
829
|
-
return selected;
|
|
830
|
-
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type PreviewResourceKind =
|
|
2
|
+
| 'webglContext'
|
|
3
|
+
| 'animationFrame'
|
|
4
|
+
| 'resizeObserver'
|
|
5
|
+
| 'objectUrl';
|
|
6
|
+
|
|
7
|
+
const current: Record<PreviewResourceKind, number> = {
|
|
8
|
+
webglContext: 0,
|
|
9
|
+
animationFrame: 0,
|
|
10
|
+
resizeObserver: 0,
|
|
11
|
+
objectUrl: 0,
|
|
12
|
+
};
|
|
13
|
+
const peaks = { ...current };
|
|
14
|
+
|
|
15
|
+
/** Local diagnostic counter used by stress tests and the Debugger; never uploads identifiers. */
|
|
16
|
+
export function registerPreviewResource(kind: PreviewResourceKind): () => void {
|
|
17
|
+
current[kind]++;
|
|
18
|
+
peaks[kind] = Math.max(peaks[kind], current[kind]);
|
|
19
|
+
let released = false;
|
|
20
|
+
return () => {
|
|
21
|
+
if (released) return;
|
|
22
|
+
released = true;
|
|
23
|
+
current[kind] = Math.max(0, current[kind] - 1);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -105,50 +105,14 @@ function forwardedCallsiteOid(object: THREE.Object3D | null | undefined): string
|
|
|
105
105
|
* same oid twice, and both mint the same shape of id: the first one seen in
|
|
106
106
|
* depth-first order keeps the bare address, later ones get `#1`, `#2`, ….
|
|
107
107
|
*
|
|
108
|
-
* The suffix is spelled HERE and nowhere else
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* presence report that stripped it back off with `split('#')[0]` — which is how
|
|
112
|
-
* a convention becomes four conventions.
|
|
108
|
+
* The suffix is spelled HERE and nowhere else: the minting walks
|
|
109
|
+
* (`projection/three.ts`, `R3fSourceAuthoringAdapter.indexGraph`), the authority
|
|
110
|
+
* check and the presence report all use this one.
|
|
113
111
|
*/
|
|
114
112
|
export function occurrenceId(baseId: string, occurrence: number): string {
|
|
115
113
|
return occurrence === 0 ? baseId : `${baseId}#${occurrence}`;
|
|
116
114
|
}
|
|
117
115
|
|
|
118
|
-
/** True for `…#1`, `…#2` — an id that is NOT its address's first occurrence. */
|
|
119
|
-
export function isOccurrenceId(id: string): boolean {
|
|
120
|
-
return id.includes('#');
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/** `id` with any occurrence suffix removed — the address all its occurrences share. */
|
|
124
|
-
export function withoutOccurrence(id: string): string {
|
|
125
|
-
const hash = id.indexOf('#');
|
|
126
|
-
return hash < 0 ? id : id.slice(0, hash);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Whether two live objects are renders of THE SAME JSX element.
|
|
131
|
-
*
|
|
132
|
-
* This is the CAPABILITY question behind an occurrence id, and it is the whole
|
|
133
|
-
* reason the two causes above must not be treated alike. N objects that share
|
|
134
|
-
* one callsite AND render one definition element are N renders of one element;
|
|
135
|
-
* the element is the unit of edit, so a literal prop on it is honestly
|
|
136
|
-
* writable and moving one moves all — which is exactly what the source says. A
|
|
137
|
-
* reparented interior element renders a DIFFERENT definition element, merely
|
|
138
|
-
* addressed by the callsite it escaped from, so writing that callsite's props
|
|
139
|
-
* would edit the instance instead of the object under the pointer.
|
|
140
|
-
*
|
|
141
|
-
* Both objects having no own oid counts as the same element: an unstamped pair
|
|
142
|
-
* is a component with several spatial roots (R3F003), which the callsite's own
|
|
143
|
-
* authoring contract already refuses on better grounds than a guess here.
|
|
144
|
-
*/
|
|
145
|
-
export function rendersSameSourceElement(
|
|
146
|
-
a: THREE.Object3D | null | undefined,
|
|
147
|
-
b: THREE.Object3D | null | undefined,
|
|
148
|
-
): boolean {
|
|
149
|
-
return ownOidOf(a) === ownOidOf(b);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
116
|
/**
|
|
153
117
|
* The oid that ADDRESSES `object` in source — the key every id, source
|
|
154
118
|
* location and prop write resolves through.
|
|
@@ -1,33 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reading the transform of a LIVE `Object3D` the editor did not write.
|
|
3
|
-
*
|
|
4
|
-
* THE TRAP, measured on the racing-game ingest (2026-08-15). A physics library
|
|
5
|
-
* that drives a node writes the node's MATRIX and turns matrix composition off:
|
|
6
|
-
* `@react-three/cannon`'s frame handler is literally
|
|
7
|
-
* `object.matrixAutoUpdate = false; object.matrix.copy(m)`. Three never
|
|
8
|
-
* decomposes that back, so `object.position`/`.quaternion`/`.scale` keep
|
|
9
|
-
* whatever they held when the body was created — forever. Everything derived
|
|
10
|
-
* from `matrixWorld` (selection brackets, bounds, three's own
|
|
11
|
-
* `TransformControls`) tracks the truth, while everything derived from
|
|
12
|
-
* `.position` shows the spawn point. Measured side by side: the driven chassis
|
|
13
|
-
* reported `[-110, 0.75, 220]` in the Inspector while the game's own state
|
|
14
|
-
* provider put it at `(-24.5, 0.85, 186.2)`.
|
|
15
|
-
*
|
|
16
|
-
* That mismatch is worse than a wrong number: origin markers and gizmo anchors
|
|
17
|
-
* derived from `.position` sit somewhere the object is not, while the bounding
|
|
18
|
-
* box around them is correct, so the editor contradicts itself on screen.
|
|
19
|
-
*
|
|
20
|
-
* THE RULE: **when a node owns its own matrix (`matrixAutoUpdate === false`),
|
|
21
|
-
* the MATRIX is the transform.** Decompose it — through three's own
|
|
22
|
-
* `Matrix4.decompose`, never a re-derivation. Otherwise the vector fields are
|
|
23
|
-
* authoritative and are read directly: deliberately not "always decompose",
|
|
24
|
-
* because for an ordinary node `matrix` is one frame BEHIND a write the editor
|
|
25
|
-
* just made, and reading it back would make a gizmo drag stutter.
|
|
26
|
-
*
|
|
27
|
-
* Nothing here is library-specific: the predicate is three's own flag, so any
|
|
28
|
-
* driver following the same convention (cannon, a custom integrator, an
|
|
29
|
-
* animation system baking matrices) is covered without naming it.
|
|
30
|
-
*/
|
|
1
|
+
/** Read matrix-driven Object3D transforms by decomposing matrix when matrixAutoUpdate is false; otherwise use position, quaternion and scale. Do not rewrite the object. */
|
|
31
2
|
|
|
32
3
|
import * as THREE from 'three';
|
|
33
4
|
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Lightweight registry for live Object3D document sessions.
|
|
3
3
|
*
|
|
4
|
-
* State/control readers
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* diagnostic-rendering graph during a plain Scene boot. The class remains the
|
|
8
|
-
* native session type; this module owns only its live identities.
|
|
4
|
+
* State/control readers find sessions constructed by their documents. The implementation
|
|
5
|
+
* dependency is type-only; this module owns live identities and lazily loads the document
|
|
6
|
+
* toolbar without importing the session's rendering implementation.
|
|
9
7
|
*/
|
|
10
|
-
import { startingPresentation, viewGridVisible, viewPresentationBinding } from '@volter/sdk/
|
|
8
|
+
import { startingPresentation, viewGridVisible, viewPresentationBinding } from '@volter/sdk/viewport-presentation';
|
|
11
9
|
import {
|
|
12
10
|
type DocumentViewport,
|
|
13
11
|
registerDocumentViewport,
|
|
14
|
-
} from '@volter/sdk/
|
|
12
|
+
} from '@volter/sdk/document-viewports';
|
|
15
13
|
import { lazy } from 'react';
|
|
16
14
|
import type { Object3DDocumentSession } from './object3d-document-session';
|
|
17
|
-
import { registerDocumentStageSession } from '@volter/sdk/
|
|
15
|
+
import { registerDocumentStageSession } from '@volter/sdk/document-stage-sessions';
|
|
18
16
|
|
|
19
17
|
// The document header's shading, helpers and capture menus. Behind `lazy()`, so
|
|
20
18
|
// this registry stays the light read it is for every other caller.
|
|
@@ -66,7 +64,7 @@ export function registerObject3DDocumentSession(
|
|
|
66
64
|
const xyz = ([x, y, z]: readonly [number, number, number]) => ({ x, y, z });
|
|
67
65
|
|
|
68
66
|
/** An Object3D document's own viewport: its session's camera, view mode, grid,
|
|
69
|
-
* framing, selection and photograph (`@volter/sdk/
|
|
67
|
+
* framing, selection and photograph (`@volter/sdk/document-viewports`). */
|
|
70
68
|
function object3DDocumentViewport(session: Object3DDocumentSession): DocumentViewport {
|
|
71
69
|
type Preset = Parameters<Object3DDocumentSession['setViewPreset']>[0];
|
|
72
70
|
type Mode = Parameters<Object3DDocumentSession['setMode']>[0];
|
|
@@ -155,9 +153,3 @@ export function subscribeObject3DDocumentSessions(listener: () => void): () => v
|
|
|
155
153
|
export function object3DDocumentSessionsVersion(): number {
|
|
156
154
|
return registryVersion;
|
|
157
155
|
}
|
|
158
|
-
|
|
159
|
-
export function __resetObject3DDocumentSessionsForTest(): void {
|
|
160
|
-
sessions.clear();
|
|
161
|
-
preparations.clear();
|
|
162
|
-
notifyRegistry();
|
|
163
|
-
}
|