@fps-games/editor 0.1.5-beta.4 → 0.1.6-beta.1
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/build-info.json +16 -16
- package/dist/local-editor-agent-actions.d.ts +8 -1
- package/dist/local-editor-agent-actions.d.ts.map +1 -1
- package/dist/local-editor-agent-actions.js +171 -12
- package/dist/local-editor-agent-actions.js.map +1 -1
- package/dist/local-editor-agent-context.d.ts +29 -1
- package/dist/local-editor-agent-context.d.ts.map +1 -1
- package/dist/local-editor-agent-context.js +403 -0
- package/dist/local-editor-agent-context.js.map +1 -1
- package/dist/local-editor-harness.d.ts +103 -5
- package/dist/local-editor-harness.d.ts.map +1 -1
- package/dist/local-editor-harness.js +1982 -101
- package/dist/local-editor-harness.js.map +1 -1
- package/dist/local-editor-marker-graph.d.ts +92 -0
- package/dist/local-editor-marker-graph.d.ts.map +1 -0
- package/dist/local-editor-marker-graph.js +1432 -0
- package/dist/local-editor-marker-graph.js.map +1 -0
- package/dist/local-editor-performance-stats.js +1 -1
- package/dist/local-editor-performance-stats.js.map +1 -1
- package/dist/playable-babylon-facade.d.ts +2 -2
- package/dist/playable-babylon-facade.d.ts.map +1 -1
- package/dist/playable-babylon-facade.js +1 -1
- package/dist/playable-babylon-facade.js.map +1 -1
- package/dist/playable-local-editor-host.d.ts +52 -7
- package/dist/playable-local-editor-host.d.ts.map +1 -1
- package/dist/playable-local-editor-host.js +23 -1
- package/dist/playable-local-editor-host.js.map +1 -1
- package/dist/playable-sdk.d.ts +4 -2
- package/dist/playable-sdk.d.ts.map +1 -1
- package/dist/playable-sdk.js +2 -1
- package/dist/playable-sdk.js.map +1 -1
- package/node_modules/@fps-games/babylon-renderer/package.json +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/camera-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/camera-controller.js +11 -0
- package/node_modules/@fps-games/editor-babylon/dist/camera-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/editor-sky.d.ts +3 -1
- package/node_modules/@fps-games/editor-babylon/dist/editor-sky.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/editor-sky.js +114 -18
- package/node_modules/@fps-games/editor-babylon/dist/editor-sky.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/editor-world.d.ts +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/editor-world.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/editor-world.js +3 -0
- package/node_modules/@fps-games/editor-babylon/dist/editor-world.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/index.d.ts +3 -0
- package/node_modules/@fps-games/editor-babylon/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/index.js +3 -0
- package/node_modules/@fps-games/editor-babylon/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/marker-overlay.d.ts +52 -0
- package/node_modules/@fps-games/editor-babylon/dist/marker-overlay.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/marker-overlay.js +1395 -0
- package/node_modules/@fps-games/editor-babylon/dist/marker-overlay.js.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/material-property-adapter.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/material-property-adapter.js +4 -65
- package/node_modules/@fps-games/editor-babylon/dist/material-property-adapter.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/material-slot-source-resolver.d.ts +28 -0
- package/node_modules/@fps-games/editor-babylon/dist/material-slot-source-resolver.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/material-slot-source-resolver.js +235 -0
- package/node_modules/@fps-games/editor-babylon/dist/material-slot-source-resolver.js.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/prefab-comparison-preview-controller.d.ts +37 -0
- package/node_modules/@fps-games/editor-babylon/dist/prefab-comparison-preview-controller.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/prefab-comparison-preview-controller.js +451 -0
- package/node_modules/@fps-games/editor-babylon/dist/prefab-comparison-preview-controller.js.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.js +24 -10
- package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.d.ts +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.js +20 -4
- package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection-source-owner-path.d.ts +9 -0
- package/node_modules/@fps-games/editor-babylon/dist/projection-source-owner-path.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/projection-source-owner-path.js +64 -0
- package/node_modules/@fps-games/editor-babylon/dist/projection-source-owner-path.js.map +1 -0
- package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts +44 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-babylon/dist/projection.js +311 -70
- package/node_modules/@fps-games/editor-babylon/dist/projection.js.map +1 -1
- package/node_modules/@fps-games/editor-babylon/package.json +5 -5
- package/node_modules/@fps-games/editor-browser/dist/index.d.ts +5 -2
- package/node_modules/@fps-games/editor-browser/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/index.js +2 -0
- package/node_modules/@fps-games/editor-browser/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-asset-kind.d.ts +5 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-asset-kind.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-asset-kind.js +23 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-asset-kind.js.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.js +69 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.js +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts +2 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js +38 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.js +8 -2
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js +7 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panel-registry.js +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panel-registry.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts +4 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js +1471 -29
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.d.ts +52 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.js +131 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.js.map +1 -0
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-primitives.d.ts +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-primitives.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-shared.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-shared.js +9 -2
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-shared.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts +234 -3
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.d.ts +10 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.js +3 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +4 -3
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +1274 -55
- package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
- package/node_modules/@fps-games/editor-browser/package.json +3 -3
- package/node_modules/@fps-games/editor-core/dist/scene-graph.d.ts +1 -1
- package/node_modules/@fps-games/editor-core/dist/scene-graph.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/viewport-tools.d.ts +2 -0
- package/node_modules/@fps-games/editor-core/dist/viewport-tools.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-core/dist/viewport-tools.js +1 -0
- package/node_modules/@fps-games/editor-core/dist/viewport-tools.js.map +1 -1
- package/node_modules/@fps-games/editor-core/package.json +2 -2
- package/node_modules/@fps-games/editor-forge-play/package.json +2 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/catalog.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/catalog.js +17 -3
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/catalog.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/document.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/document.js +2 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/document.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/types.d.ts +3 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js +68 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.d.ts +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.js +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts +56 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js +531 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts +103 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.d.ts +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.js +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js +9 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.js +3 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.js +3 -7
- package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.js +6 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/types.d.ts +2 -10
- package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js +8 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js +66 -31
- package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts +2 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/protocol.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/protocol.js +40 -2
- package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/protocol.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts +1 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js +20 -0
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js +68 -27
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js +7 -4
- package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/hierarchy.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/hierarchy.js +2 -1
- package/node_modules/@fps-games/editor-playable-sdk/dist/session/hierarchy.js.map +1 -1
- package/node_modules/@fps-games/editor-playable-sdk/package.json +3 -3
- package/node_modules/@fps-games/editor-protocol/dist/agent.d.ts +57 -3
- package/node_modules/@fps-games/editor-protocol/dist/agent.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-protocol/dist/agent.js.map +1 -1
- package/node_modules/@fps-games/editor-protocol/dist/index.d.ts +19 -0
- package/node_modules/@fps-games/editor-protocol/dist/index.d.ts.map +1 -1
- package/node_modules/@fps-games/editor-protocol/dist/index.js +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/index.js.map +1 -1
- package/node_modules/@fps-games/editor-protocol/dist/marker-graph.d.ts +128 -0
- package/node_modules/@fps-games/editor-protocol/dist/marker-graph.d.ts.map +1 -0
- package/node_modules/@fps-games/editor-protocol/dist/marker-graph.js +2 -0
- package/node_modules/@fps-games/editor-protocol/dist/marker-graph.js.map +1 -0
- package/node_modules/@fps-games/editor-protocol/package.json +1 -1
- package/package.json +8 -8
|
@@ -2,6 +2,8 @@ import { cloneEditorTransformMatrix, combineEditorTransforms, createIdentityEdit
|
|
|
2
2
|
import { applyBabylonDefaultOutline } from '@fps-games/babylon-renderer';
|
|
3
3
|
import { applyArtistMaterialProfileToRuntimeMaterial } from './material-property-adapter.js';
|
|
4
4
|
import { pickBabylonProjectionNodeIdAt, resolveBabylonPickSelectionNodeId, resolveBabylonProjectionNodeId, } from './projection-pick-resolver.js';
|
|
5
|
+
import { normalizeProjectionOwnerNodePath, readProjectionSourceNodeSegment, } from './projection-source-owner-path.js';
|
|
6
|
+
import { createMaterialSlotOwnerPathMatchKey, isMaterialSlotOwnerPathMatch, } from './material-slot-source-resolver.js';
|
|
5
7
|
const LARGE_SELECTION_EDGE_LIMIT = 200;
|
|
6
8
|
const PROJECTION_LOCAL_MATRIX_METADATA_KEY = 'editorLocalTransformMatrix';
|
|
7
9
|
const ASSET_MESH_SELECTION_SEPARATOR = '::assetMesh::';
|
|
@@ -123,6 +125,7 @@ export function createBabylonEditorProjection(options) {
|
|
|
123
125
|
const disposeProjectedNode = (projection) => {
|
|
124
126
|
projection.selectionEdgesPrewarmCancel?.();
|
|
125
127
|
projection.selectionEdgesPrewarmCancel = null;
|
|
128
|
+
projection.importStructure = null;
|
|
126
129
|
for (const animationGroup of projection.animationGroups) {
|
|
127
130
|
animationGroup.dispose?.();
|
|
128
131
|
}
|
|
@@ -261,6 +264,9 @@ export function createBabylonEditorProjection(options) {
|
|
|
261
264
|
}
|
|
262
265
|
return transforms;
|
|
263
266
|
},
|
|
267
|
+
readNodeImportStructure(nodeId) {
|
|
268
|
+
return cloneProjectionImportStructureSnapshot(projections.get(nodeId)?.importStructure ?? null);
|
|
269
|
+
},
|
|
264
270
|
setNodeTransformPreview(nodeId, transform) {
|
|
265
271
|
const projection = projections.get(nodeId);
|
|
266
272
|
if (!projection?.root)
|
|
@@ -557,9 +563,9 @@ function attachImportedProjectionResult(options, node, asset, projection, result
|
|
|
557
563
|
for (const mesh of result.meshes ?? []) {
|
|
558
564
|
mesh.isPickable = true;
|
|
559
565
|
applyProjectionRenderingToMesh(node, mesh);
|
|
560
|
-
const ownerNodePath = buildProjectionOwnerNodePath(mesh, modelRoot);
|
|
566
|
+
const ownerNodePath = buildProjectionOwnerNodePath(mesh, modelRoot, node.id);
|
|
561
567
|
if (ownerNodePath) {
|
|
562
|
-
const selectionKey = resolveProjectionAssetMeshSelectionKey(asset, ownerNodePath);
|
|
568
|
+
const selectionKey = resolveProjectionAssetMeshSelectionKey(asset, ownerNodePath, node.id);
|
|
563
569
|
mesh.metadata = {
|
|
564
570
|
...(mesh.metadata ?? {}),
|
|
565
571
|
editorProjection: {
|
|
@@ -580,12 +586,215 @@ function attachImportedProjectionResult(options, node, asset, projection, result
|
|
|
580
586
|
}
|
|
581
587
|
projection.animationGroups = result.animationGroups ?? [];
|
|
582
588
|
projection.outlineMeshes = (result.meshes ?? []).filter((mesh) => mesh.getTotalVertices?.() > 0);
|
|
589
|
+
projection.importStructure = createProjectionImportStructureSnapshot(node, asset, modelRoot, result);
|
|
583
590
|
}
|
|
584
591
|
catch (error) {
|
|
585
592
|
disposeImportedProjectionResult(result);
|
|
586
593
|
throw error;
|
|
587
594
|
}
|
|
588
595
|
}
|
|
596
|
+
function createProjectionImportStructureSnapshot(node, asset, modelRoot, result) {
|
|
597
|
+
const runtimeNodes = collectProjectionImportRuntimeNodes(modelRoot, result);
|
|
598
|
+
const nodeIdByRuntimeNode = new Map();
|
|
599
|
+
const materialIdByRuntimeMaterial = new Map();
|
|
600
|
+
const textureIdByRuntimeTexture = new Map();
|
|
601
|
+
const materialNodeIds = new Map();
|
|
602
|
+
const materialTextureIds = new Map();
|
|
603
|
+
const rootSnapshotId = 'root';
|
|
604
|
+
const snapshots = [{
|
|
605
|
+
id: rootSnapshotId,
|
|
606
|
+
parentId: null,
|
|
607
|
+
name: readProjectionRuntimeName(modelRoot, node.name ?? node.id),
|
|
608
|
+
kind: 'root',
|
|
609
|
+
}];
|
|
610
|
+
for (const runtimeNode of runtimeNodes) {
|
|
611
|
+
const snapshotId = createProjectionImportRuntimeNodeId(runtimeNode, nodeIdByRuntimeNode.size);
|
|
612
|
+
nodeIdByRuntimeNode.set(runtimeNode, snapshotId);
|
|
613
|
+
}
|
|
614
|
+
for (const runtimeNode of runtimeNodes) {
|
|
615
|
+
const snapshotId = nodeIdByRuntimeNode.get(runtimeNode);
|
|
616
|
+
if (!snapshotId)
|
|
617
|
+
continue;
|
|
618
|
+
const materialIds = readProjectionRuntimeNodeMaterials(runtimeNode)
|
|
619
|
+
.map(runtimeMaterial => getProjectionImportMaterialSnapshotId(runtimeMaterial, materialIdByRuntimeMaterial))
|
|
620
|
+
.filter((materialId) => !!materialId);
|
|
621
|
+
for (const materialId of materialIds) {
|
|
622
|
+
const nodeIds = materialNodeIds.get(materialId) ?? new Set();
|
|
623
|
+
nodeIds.add(snapshotId);
|
|
624
|
+
materialNodeIds.set(materialId, nodeIds);
|
|
625
|
+
const textureIds = readProjectionRuntimeMaterialTextures(readProjectionRuntimeNodeMaterialById(runtimeNode, runtimeNode, materialId, materialIdByRuntimeMaterial))
|
|
626
|
+
.map(runtimeTexture => getProjectionImportTextureSnapshotId(runtimeTexture, textureIdByRuntimeTexture))
|
|
627
|
+
.filter((textureId) => !!textureId);
|
|
628
|
+
const materialTextures = materialTextureIds.get(materialId) ?? new Set();
|
|
629
|
+
for (const textureId of textureIds)
|
|
630
|
+
materialTextures.add(textureId);
|
|
631
|
+
materialTextureIds.set(materialId, materialTextures);
|
|
632
|
+
}
|
|
633
|
+
snapshots.push({
|
|
634
|
+
id: snapshotId,
|
|
635
|
+
parentId: resolveProjectionImportRuntimeParentId(runtimeNode, modelRoot, nodeIdByRuntimeNode, rootSnapshotId),
|
|
636
|
+
name: readProjectionRuntimeName(runtimeNode, snapshotId),
|
|
637
|
+
kind: isProjectionRuntimeMeshLike(runtimeNode) ? 'mesh' : 'transform',
|
|
638
|
+
...readProjectionRuntimeSourceName(runtimeNode),
|
|
639
|
+
...readProjectionRuntimeOwnerNodePath(runtimeNode),
|
|
640
|
+
...(materialIds.length > 0 ? { materialIds } : {}),
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
const materials = [...materialIdByRuntimeMaterial.entries()].map(([runtimeMaterial, id]) => ({
|
|
644
|
+
id,
|
|
645
|
+
name: readProjectionRuntimeName(runtimeMaterial, id),
|
|
646
|
+
...readProjectionRuntimeKind(runtimeMaterial),
|
|
647
|
+
nodeIds: [...(materialNodeIds.get(id) ?? [])],
|
|
648
|
+
textureIds: [...(materialTextureIds.get(id) ?? [])],
|
|
649
|
+
}));
|
|
650
|
+
const textures = [...textureIdByRuntimeTexture.entries()].map(([runtimeTexture, id]) => ({
|
|
651
|
+
id,
|
|
652
|
+
name: readProjectionRuntimeName(runtimeTexture, id),
|
|
653
|
+
...readProjectionRuntimeKind(runtimeTexture),
|
|
654
|
+
...readProjectionRuntimeTextureUrl(runtimeTexture),
|
|
655
|
+
}));
|
|
656
|
+
const animations = createProjectionImportAnimationSnapshots(result.animationGroups ?? []);
|
|
657
|
+
return {
|
|
658
|
+
projectionNodeId: node.id,
|
|
659
|
+
...(asset.id ? { assetId: asset.id } : {}),
|
|
660
|
+
...(asset.sourceId ? { sourceId: asset.sourceId } : {}),
|
|
661
|
+
nodes: snapshots,
|
|
662
|
+
materials,
|
|
663
|
+
textures,
|
|
664
|
+
animations,
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
function collectProjectionImportRuntimeNodes(modelRoot, result) {
|
|
668
|
+
const known = new Set([
|
|
669
|
+
...(result.transformNodes ?? []),
|
|
670
|
+
...(result.meshes ?? []),
|
|
671
|
+
].filter(Boolean));
|
|
672
|
+
const ordered = [];
|
|
673
|
+
const visit = (runtimeNode) => {
|
|
674
|
+
for (const child of readProjectionRuntimeChildren(runtimeNode)) {
|
|
675
|
+
if (!known.has(child) || ordered.includes(child))
|
|
676
|
+
continue;
|
|
677
|
+
ordered.push(child);
|
|
678
|
+
visit(child);
|
|
679
|
+
}
|
|
680
|
+
};
|
|
681
|
+
visit(modelRoot);
|
|
682
|
+
for (const runtimeNode of known) {
|
|
683
|
+
if (!ordered.includes(runtimeNode))
|
|
684
|
+
ordered.push(runtimeNode);
|
|
685
|
+
}
|
|
686
|
+
return ordered;
|
|
687
|
+
}
|
|
688
|
+
function readProjectionRuntimeChildren(runtimeNode) {
|
|
689
|
+
const children = runtimeNode?.getChildren?.();
|
|
690
|
+
return Array.isArray(children) ? children : [];
|
|
691
|
+
}
|
|
692
|
+
function createProjectionImportRuntimeNodeId(runtimeNode, index) {
|
|
693
|
+
const sourceName = readProjectionSourceNodeSegment(runtimeNode);
|
|
694
|
+
const rawName = sourceName || runtimeNode?.name || runtimeNode?.id || `node-${index + 1}`;
|
|
695
|
+
return `${isProjectionRuntimeMeshLike(runtimeNode) ? 'mesh' : 'node'}:${sanitizeProjectionImportSnapshotId(rawName)}:${index + 1}`;
|
|
696
|
+
}
|
|
697
|
+
function resolveProjectionImportRuntimeParentId(runtimeNode, modelRoot, nodeIdByRuntimeNode, rootSnapshotId) {
|
|
698
|
+
const parent = runtimeNode?.parent ?? null;
|
|
699
|
+
if (!parent || parent === modelRoot)
|
|
700
|
+
return rootSnapshotId;
|
|
701
|
+
return nodeIdByRuntimeNode.get(parent) ?? rootSnapshotId;
|
|
702
|
+
}
|
|
703
|
+
function isProjectionRuntimeMeshLike(runtimeNode) {
|
|
704
|
+
return typeof runtimeNode?.getTotalVertices === 'function';
|
|
705
|
+
}
|
|
706
|
+
function readProjectionRuntimeNodeMaterials(runtimeNode) {
|
|
707
|
+
const material = runtimeNode?.material;
|
|
708
|
+
if (!material)
|
|
709
|
+
return [];
|
|
710
|
+
const subMaterials = material.subMaterials;
|
|
711
|
+
if (Array.isArray(subMaterials) && subMaterials.length > 0) {
|
|
712
|
+
return subMaterials.filter(Boolean);
|
|
713
|
+
}
|
|
714
|
+
return [material];
|
|
715
|
+
}
|
|
716
|
+
function readProjectionRuntimeNodeMaterialById(runtimeNode, _fallbackNode, materialId, materialIdByRuntimeMaterial) {
|
|
717
|
+
for (const material of readProjectionRuntimeNodeMaterials(runtimeNode)) {
|
|
718
|
+
if (materialIdByRuntimeMaterial.get(material) === materialId)
|
|
719
|
+
return material;
|
|
720
|
+
}
|
|
721
|
+
return null;
|
|
722
|
+
}
|
|
723
|
+
function getProjectionImportMaterialSnapshotId(runtimeMaterial, materialIdByRuntimeMaterial) {
|
|
724
|
+
if (!runtimeMaterial)
|
|
725
|
+
return null;
|
|
726
|
+
const existing = materialIdByRuntimeMaterial.get(runtimeMaterial);
|
|
727
|
+
if (existing)
|
|
728
|
+
return existing;
|
|
729
|
+
const id = `material:${sanitizeProjectionImportSnapshotId(readProjectionRuntimeName(runtimeMaterial, 'material'))}:${materialIdByRuntimeMaterial.size + 1}`;
|
|
730
|
+
materialIdByRuntimeMaterial.set(runtimeMaterial, id);
|
|
731
|
+
return id;
|
|
732
|
+
}
|
|
733
|
+
function readProjectionRuntimeMaterialTextures(runtimeMaterial) {
|
|
734
|
+
if (!runtimeMaterial)
|
|
735
|
+
return [];
|
|
736
|
+
const textures = runtimeMaterial.getActiveTextures?.();
|
|
737
|
+
return Array.isArray(textures) ? textures.filter(Boolean) : [];
|
|
738
|
+
}
|
|
739
|
+
function getProjectionImportTextureSnapshotId(runtimeTexture, textureIdByRuntimeTexture) {
|
|
740
|
+
if (!runtimeTexture)
|
|
741
|
+
return null;
|
|
742
|
+
const existing = textureIdByRuntimeTexture.get(runtimeTexture);
|
|
743
|
+
if (existing)
|
|
744
|
+
return existing;
|
|
745
|
+
const name = readProjectionRuntimeTextureUrl(runtimeTexture).url
|
|
746
|
+
?? readProjectionRuntimeName(runtimeTexture, 'texture');
|
|
747
|
+
const id = `texture:${sanitizeProjectionImportSnapshotId(name)}:${textureIdByRuntimeTexture.size + 1}`;
|
|
748
|
+
textureIdByRuntimeTexture.set(runtimeTexture, id);
|
|
749
|
+
return id;
|
|
750
|
+
}
|
|
751
|
+
function createProjectionImportAnimationSnapshots(animationGroups) {
|
|
752
|
+
return animationGroups.filter(Boolean).map((animationGroup, index) => ({
|
|
753
|
+
id: `animation:${sanitizeProjectionImportSnapshotId(readProjectionRuntimeName(animationGroup, 'animation'))}:${index + 1}`,
|
|
754
|
+
name: readProjectionRuntimeName(animationGroup, `Animation ${index + 1}`),
|
|
755
|
+
}));
|
|
756
|
+
}
|
|
757
|
+
function readProjectionRuntimeName(runtimeObject, fallback) {
|
|
758
|
+
const name = runtimeObject?.name ?? runtimeObject?.id;
|
|
759
|
+
return typeof name === 'string' && name.trim() ? name.trim() : fallback;
|
|
760
|
+
}
|
|
761
|
+
function readProjectionRuntimeKind(runtimeObject) {
|
|
762
|
+
const kind = runtimeObject?.getClassName?.();
|
|
763
|
+
return typeof kind === 'string' && kind.trim() ? { kind: kind.trim() } : {};
|
|
764
|
+
}
|
|
765
|
+
function readProjectionRuntimeTextureUrl(runtimeTexture) {
|
|
766
|
+
const url = runtimeTexture?.url ?? runtimeTexture?.name;
|
|
767
|
+
return typeof url === 'string' && url.trim() ? { url: url.trim() } : {};
|
|
768
|
+
}
|
|
769
|
+
function readProjectionRuntimeSourceName(runtimeNode) {
|
|
770
|
+
const sourceName = readProjectionSourceNodeSegment(runtimeNode);
|
|
771
|
+
return sourceName ? { sourceName } : {};
|
|
772
|
+
}
|
|
773
|
+
function readProjectionRuntimeOwnerNodePath(runtimeNode) {
|
|
774
|
+
const ownerNodePath = runtimeNode?.metadata?.editorProjection?.ownerNodePath;
|
|
775
|
+
return typeof ownerNodePath === 'string' && ownerNodePath.trim() ? { ownerNodePath: ownerNodePath.trim() } : {};
|
|
776
|
+
}
|
|
777
|
+
function sanitizeProjectionImportSnapshotId(value) {
|
|
778
|
+
return value.trim().toLowerCase().replace(/[^a-z0-9_.:-]+/gi, '-').replace(/^-+|-+$/g, '') || 'item';
|
|
779
|
+
}
|
|
780
|
+
function cloneProjectionImportStructureSnapshot(snapshot) {
|
|
781
|
+
if (!snapshot)
|
|
782
|
+
return null;
|
|
783
|
+
return {
|
|
784
|
+
...snapshot,
|
|
785
|
+
nodes: snapshot.nodes.map(item => ({
|
|
786
|
+
...item,
|
|
787
|
+
...(item.materialIds ? { materialIds: [...item.materialIds] } : {}),
|
|
788
|
+
})),
|
|
789
|
+
materials: snapshot.materials.map(item => ({
|
|
790
|
+
...item,
|
|
791
|
+
nodeIds: [...item.nodeIds],
|
|
792
|
+
textureIds: [...item.textureIds],
|
|
793
|
+
})),
|
|
794
|
+
textures: snapshot.textures.map(item => ({ ...item })),
|
|
795
|
+
animations: snapshot.animations.map(item => ({ ...item })),
|
|
796
|
+
};
|
|
797
|
+
}
|
|
589
798
|
function disposeImportedProjectionResult(result) {
|
|
590
799
|
for (const animationGroup of result.animationGroups ?? []) {
|
|
591
800
|
animationGroup.dispose?.();
|
|
@@ -654,6 +863,8 @@ function attachDirectionalLightProjection(babylon, scene, node, projection) {
|
|
|
654
863
|
light.setEnabled?.(node.active !== false);
|
|
655
864
|
projection.runtimeObjects.push(light);
|
|
656
865
|
}
|
|
866
|
+
if (!settings.helperVisible)
|
|
867
|
+
return;
|
|
657
868
|
const helper = MeshBuilder.CreateBox(`${node.id}.lightHelper`, {
|
|
658
869
|
size: 0.28,
|
|
659
870
|
}, scene);
|
|
@@ -759,9 +970,9 @@ function createPrimitiveProjectionMesh(babylon, scene, node, options) {
|
|
|
759
970
|
return mesh;
|
|
760
971
|
}
|
|
761
972
|
function applyProjectionArtistMaterialProfilesToMeshes(options, node, modelRoot, meshes) {
|
|
762
|
-
const
|
|
973
|
+
const slotBindings = createProjectionMaterialSlotBindings(node);
|
|
763
974
|
const hasRootProfile = !!node.artistMaterialProfile;
|
|
764
|
-
const hasSlotProfiles =
|
|
975
|
+
const hasSlotProfiles = slotBindings.length > 0;
|
|
765
976
|
if (!hasRootProfile && !hasSlotProfiles)
|
|
766
977
|
return [];
|
|
767
978
|
const clonedMaterials = [];
|
|
@@ -783,16 +994,16 @@ function applyProjectionArtistMaterialProfilesToMeshes(options, node, modelRoot,
|
|
|
783
994
|
const material = mesh?.material;
|
|
784
995
|
if (!material)
|
|
785
996
|
continue;
|
|
786
|
-
const ownerNodePath = buildProjectionOwnerNodePath(mesh, modelRoot);
|
|
787
|
-
const
|
|
788
|
-
if (!
|
|
997
|
+
const ownerNodePath = buildProjectionOwnerNodePath(mesh, modelRoot, node.id);
|
|
998
|
+
const slotBinding = resolveProjectionSlotBinding(slotBindings, ownerNodePath, node.id);
|
|
999
|
+
if (!slotBinding)
|
|
789
1000
|
continue;
|
|
790
1001
|
const slotMaterial = detachProjectionSlotMaterial(mesh, materialCounts, ownerNodePath);
|
|
791
1002
|
if (!slotMaterial)
|
|
792
1003
|
continue;
|
|
793
1004
|
if (slotMaterial !== material)
|
|
794
1005
|
clonedMaterials.push(slotMaterial);
|
|
795
|
-
applyProjectionArtistMaterialProfile(options, slotMaterial,
|
|
1006
|
+
applyProjectionArtistMaterialProfile(options, slotMaterial, slotBinding.profile);
|
|
796
1007
|
}
|
|
797
1008
|
return clonedMaterials;
|
|
798
1009
|
}
|
|
@@ -804,29 +1015,87 @@ function applyProjectionArtistMaterialProfile(options, material, profile) {
|
|
|
804
1015
|
resolveTextureUrl: options.resolveTextureUrl,
|
|
805
1016
|
});
|
|
806
1017
|
}
|
|
807
|
-
function
|
|
1018
|
+
function createProjectionMaterialSlotBindings(node) {
|
|
1019
|
+
const bindings = [];
|
|
1020
|
+
const occupiedOwnerPaths = new Set();
|
|
1021
|
+
for (const binding of node.artistMaterialSlotBindings ?? []) {
|
|
1022
|
+
const profile = binding?.profile;
|
|
1023
|
+
const slot = createProjectionMaterialSlotDescriptor(binding?.slot, node.id);
|
|
1024
|
+
if (!profile || !slot)
|
|
1025
|
+
continue;
|
|
1026
|
+
bindings.push({ slot, profile });
|
|
1027
|
+
occupiedOwnerPaths.add(slot.matchKey);
|
|
1028
|
+
}
|
|
1029
|
+
for (const [ownerNodePath, profile] of Object.entries(node.artistMaterialSlotProfiles ?? {})) {
|
|
1030
|
+
const slot = createProjectionMaterialSlotDescriptor({ ownerNodePath }, node.id);
|
|
1031
|
+
if (!profile || !slot || occupiedOwnerPaths.has(slot.matchKey))
|
|
1032
|
+
continue;
|
|
1033
|
+
bindings.push({ slot, profile });
|
|
1034
|
+
occupiedOwnerPaths.add(slot.matchKey);
|
|
1035
|
+
}
|
|
1036
|
+
return bindings;
|
|
1037
|
+
}
|
|
1038
|
+
function createProjectionMaterialSlotDescriptor(value, projectionNodeId) {
|
|
1039
|
+
if (!value || typeof value !== 'object')
|
|
1040
|
+
return null;
|
|
1041
|
+
const ownerNodePath = typeof value.ownerNodePath === 'string'
|
|
1042
|
+
? normalizeProjectionOwnerNodePath(value.ownerNodePath, { projectionNodeId })
|
|
1043
|
+
: '';
|
|
1044
|
+
if (!ownerNodePath)
|
|
1045
|
+
return null;
|
|
1046
|
+
const slotId = typeof value.slotId === 'string' && value.slotId.trim() ? value.slotId.trim() : '';
|
|
1047
|
+
const label = typeof value.label === 'string' && value.label.trim() ? value.label.trim() : '';
|
|
1048
|
+
const nodeIndex = Number.isInteger(value.nodeIndex) ? value.nodeIndex : undefined;
|
|
1049
|
+
const nodeIndexPath = Array.isArray(value.nodeIndexPath)
|
|
1050
|
+
? value.nodeIndexPath.filter((item) => Number.isInteger(item))
|
|
1051
|
+
: undefined;
|
|
1052
|
+
const meshIndex = Number.isInteger(value.meshIndex) ? value.meshIndex : undefined;
|
|
1053
|
+
const primitiveIndex = Number.isInteger(value.primitiveIndex) ? value.primitiveIndex : undefined;
|
|
1054
|
+
const sourceMaterialIndex = Number.isInteger(value.sourceMaterialIndex) ? value.sourceMaterialIndex : undefined;
|
|
1055
|
+
const sourceMaterialIndices = Array.isArray(value.sourceMaterialIndices)
|
|
1056
|
+
? value.sourceMaterialIndices.filter((item) => Number.isInteger(item))
|
|
1057
|
+
: undefined;
|
|
1058
|
+
const materialName = typeof value.materialName === 'string' && value.materialName.trim() ? value.materialName.trim() : '';
|
|
1059
|
+
const materialNames = Array.isArray(value.materialNames)
|
|
1060
|
+
? value.materialNames.filter((item) => typeof item === 'string' && !!item.trim()).map(item => item.trim())
|
|
1061
|
+
: undefined;
|
|
1062
|
+
return {
|
|
1063
|
+
...(slotId ? { slotId } : {}),
|
|
1064
|
+
ownerNodePath,
|
|
1065
|
+
...(label ? { label } : {}),
|
|
1066
|
+
...(nodeIndex != null ? { nodeIndex } : {}),
|
|
1067
|
+
...(nodeIndexPath && nodeIndexPath.length > 0 ? { nodeIndexPath } : {}),
|
|
1068
|
+
...(meshIndex != null ? { meshIndex } : {}),
|
|
1069
|
+
...(primitiveIndex != null ? { primitiveIndex } : {}),
|
|
1070
|
+
...(sourceMaterialIndex != null ? { sourceMaterialIndex } : {}),
|
|
1071
|
+
...(sourceMaterialIndices && sourceMaterialIndices.length > 0
|
|
1072
|
+
? { sourceMaterialIndices }
|
|
1073
|
+
: {}),
|
|
1074
|
+
...(materialName ? { materialName } : {}),
|
|
1075
|
+
...(materialNames && materialNames.length > 0 ? { materialNames } : {}),
|
|
1076
|
+
key: slotId || ownerNodePath,
|
|
1077
|
+
normalizedOwnerNodePath: ownerNodePath,
|
|
1078
|
+
matchKey: createMaterialSlotOwnerPathMatchKey(ownerNodePath, { projectionNodeId }),
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
function resolveProjectionSlotBinding(slotBindings, ownerNodePath, projectionNodeId) {
|
|
808
1082
|
if (ownerNodePath == null)
|
|
809
1083
|
return null;
|
|
810
|
-
const
|
|
811
|
-
|
|
812
|
-
return direct;
|
|
813
|
-
const normalized = normalizeProjectionOwnerNodePath(ownerNodePath);
|
|
814
|
-
if (normalized !== ownerNodePath && slotProfiles[normalized])
|
|
815
|
-
return slotProfiles[normalized];
|
|
1084
|
+
const normalized = normalizeProjectionOwnerNodePath(ownerNodePath, { projectionNodeId });
|
|
1085
|
+
const normalizedMatchKey = createMaterialSlotOwnerPathMatchKey(normalized, { projectionNodeId });
|
|
816
1086
|
let descendantMatch = null;
|
|
817
|
-
for (const
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
descendantMatch = { path: normalizedCandidate, profile };
|
|
1087
|
+
for (const binding of slotBindings) {
|
|
1088
|
+
if (binding.slot.matchKey === normalizedMatchKey)
|
|
1089
|
+
return binding;
|
|
1090
|
+
if (isMaterialSlotOwnerPathMatch(normalized, binding.slot.normalizedOwnerNodePath, { projectionNodeId })) {
|
|
1091
|
+
if (!descendantMatch || binding.slot.matchKey.length > descendantMatch.slot.matchKey.length) {
|
|
1092
|
+
descendantMatch = binding;
|
|
824
1093
|
}
|
|
825
1094
|
}
|
|
826
1095
|
}
|
|
827
|
-
return descendantMatch
|
|
1096
|
+
return descendantMatch;
|
|
828
1097
|
}
|
|
829
|
-
function buildProjectionOwnerNodePath(node, rootNode) {
|
|
1098
|
+
function buildProjectionOwnerNodePath(node, rootNode, projectionNodeId) {
|
|
830
1099
|
if (!node || !rootNode || node === rootNode)
|
|
831
1100
|
return '';
|
|
832
1101
|
const segments = [];
|
|
@@ -840,9 +1109,12 @@ function buildProjectionOwnerNodePath(node, rootNode) {
|
|
|
840
1109
|
}
|
|
841
1110
|
if (current !== rootNode)
|
|
842
1111
|
return null;
|
|
843
|
-
return segments.reverse().join('/');
|
|
1112
|
+
return normalizeProjectionOwnerNodePath(segments.reverse().join('/'), { projectionNodeId });
|
|
844
1113
|
}
|
|
845
1114
|
function stableProjectionNodeSegment(node) {
|
|
1115
|
+
const sourceSegment = readProjectionSourceNodeSegment(node);
|
|
1116
|
+
if (sourceSegment)
|
|
1117
|
+
return sourceSegment;
|
|
846
1118
|
const candidates = [node?.name, node?.id];
|
|
847
1119
|
for (const candidate of candidates) {
|
|
848
1120
|
if (typeof candidate !== 'string')
|
|
@@ -853,59 +1125,36 @@ function stableProjectionNodeSegment(node) {
|
|
|
853
1125
|
}
|
|
854
1126
|
return null;
|
|
855
1127
|
}
|
|
856
|
-
function normalizeProjectionOwnerNodePath(path) {
|
|
857
|
-
const segments = path
|
|
858
|
-
.split('/')
|
|
859
|
-
.map(normalizeProjectionOwnerPathSegment)
|
|
860
|
-
.filter(Boolean);
|
|
861
|
-
while (segments.length > 0 && isSyntheticProjectionOwnerRootSegment(segments[0])) {
|
|
862
|
-
segments.shift();
|
|
863
|
-
}
|
|
864
|
-
return segments.join('/');
|
|
865
|
-
}
|
|
866
|
-
function normalizeProjectionOwnerPathSegment(segment) {
|
|
867
|
-
const trimmed = segment.trim();
|
|
868
|
-
return trimmed.includes(':') ? trimmed.slice(trimmed.lastIndexOf(':') + 1) : trimmed;
|
|
869
|
-
}
|
|
870
|
-
function isSyntheticProjectionOwnerRootSegment(segment) {
|
|
871
|
-
return segment === '__root__';
|
|
872
|
-
}
|
|
873
|
-
function isProjectionOwnerPathDescendant(ownerNodePath, candidateAncestorPath) {
|
|
874
|
-
if (!ownerNodePath || !candidateAncestorPath)
|
|
875
|
-
return false;
|
|
876
|
-
return ownerNodePath.startsWith(`${candidateAncestorPath}/`);
|
|
877
|
-
}
|
|
878
1128
|
function createAssetMeshProjectionNodeId(rootNodeId, ownerNodePath) {
|
|
879
1129
|
return `${rootNodeId}${ASSET_MESH_SELECTION_SEPARATOR}${encodeURIComponent(ownerNodePath)}`;
|
|
880
1130
|
}
|
|
881
|
-
function resolveProjectionAssetMeshSelectionKey(asset, ownerNodePath) {
|
|
882
|
-
const normalizedOwnerPath = normalizeProjectionOwnerNodePath(ownerNodePath);
|
|
1131
|
+
function resolveProjectionAssetMeshSelectionKey(asset, ownerNodePath, projectionNodeId) {
|
|
1132
|
+
const normalizedOwnerPath = normalizeProjectionOwnerNodePath(ownerNodePath, { projectionNodeId });
|
|
883
1133
|
let bestSlot = null;
|
|
884
|
-
for (const slot of readProjectionAssetMaterialSlots(asset)) {
|
|
885
|
-
if (!
|
|
1134
|
+
for (const slot of readProjectionAssetMaterialSlots(asset, projectionNodeId)) {
|
|
1135
|
+
if (!isMaterialSlotOwnerPathMatch(normalizedOwnerPath, slot.normalizedOwnerNodePath, { projectionNodeId }))
|
|
886
1136
|
continue;
|
|
887
|
-
if (!bestSlot || slot.
|
|
1137
|
+
if (!bestSlot || slot.matchKey.length > bestSlot.matchKey.length) {
|
|
888
1138
|
bestSlot = slot;
|
|
889
1139
|
}
|
|
890
1140
|
}
|
|
891
1141
|
return bestSlot?.key ?? ownerNodePath;
|
|
892
1142
|
}
|
|
893
|
-
function readProjectionAssetMaterialSlots(asset) {
|
|
1143
|
+
function readProjectionAssetMaterialSlots(asset, projectionNodeId) {
|
|
894
1144
|
const rawSlots = asset.metadata?.materialSlots;
|
|
895
1145
|
if (!Array.isArray(rawSlots))
|
|
896
1146
|
return [];
|
|
897
1147
|
const slots = [];
|
|
898
1148
|
for (const rawSlot of rawSlots) {
|
|
899
|
-
const slot = readProjectionAssetMaterialSlot(rawSlot);
|
|
1149
|
+
const slot = readProjectionAssetMaterialSlot(rawSlot, projectionNodeId);
|
|
900
1150
|
if (slot)
|
|
901
1151
|
slots.push(slot);
|
|
902
1152
|
}
|
|
903
1153
|
return slots;
|
|
904
1154
|
}
|
|
905
|
-
function readProjectionAssetMaterialSlot(value) {
|
|
1155
|
+
function readProjectionAssetMaterialSlot(value, projectionNodeId) {
|
|
906
1156
|
if (typeof value === 'string') {
|
|
907
|
-
|
|
908
|
-
return path ? { key: path, path } : null;
|
|
1157
|
+
return createProjectionMaterialSlotDescriptor({ ownerNodePath: value }, projectionNodeId);
|
|
909
1158
|
}
|
|
910
1159
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
911
1160
|
return null;
|
|
@@ -913,23 +1162,11 @@ function readProjectionAssetMaterialSlot(value) {
|
|
|
913
1162
|
const rawOwnerPath = readProjectionAssetMaterialSlotString(record.ownerNodePath)
|
|
914
1163
|
|| readProjectionAssetMaterialSlotString(record.path)
|
|
915
1164
|
|| readProjectionAssetMaterialSlotString(record.name);
|
|
916
|
-
|
|
917
|
-
if (!path)
|
|
918
|
-
return null;
|
|
919
|
-
const slotId = readProjectionAssetMaterialSlotString(record.slotId);
|
|
920
|
-
return {
|
|
921
|
-
key: slotId || path,
|
|
922
|
-
path,
|
|
923
|
-
};
|
|
1165
|
+
return createProjectionMaterialSlotDescriptor({ ...record, ownerNodePath: rawOwnerPath }, projectionNodeId);
|
|
924
1166
|
}
|
|
925
1167
|
function readProjectionAssetMaterialSlotString(value) {
|
|
926
1168
|
return typeof value === 'string' ? value.trim() : '';
|
|
927
1169
|
}
|
|
928
|
-
function isProjectionOwnerPathSlotMatch(ownerNodePath, slotOwnerPath) {
|
|
929
|
-
if (!ownerNodePath || !slotOwnerPath)
|
|
930
|
-
return false;
|
|
931
|
-
return ownerNodePath === slotOwnerPath || isProjectionOwnerPathDescendant(ownerNodePath, slotOwnerPath);
|
|
932
|
-
}
|
|
933
1170
|
function countProjectionMeshMaterials(meshes) {
|
|
934
1171
|
const counts = new Map();
|
|
935
1172
|
for (const mesh of meshes) {
|
|
@@ -1125,6 +1362,8 @@ function attachHemisphericLightProjection(babylon, scene, node, projection) {
|
|
|
1125
1362
|
light.setEnabled?.(node.active !== false);
|
|
1126
1363
|
projection.runtimeObjects.push(light);
|
|
1127
1364
|
}
|
|
1365
|
+
if (!settings.helperVisible)
|
|
1366
|
+
return;
|
|
1128
1367
|
const helper = MeshBuilder.CreateSphere?.(`${node.id}.hemisphericLightHelper`, {
|
|
1129
1368
|
diameter: 0.32,
|
|
1130
1369
|
segments: 18,
|
|
@@ -1271,6 +1510,7 @@ function readProjectionDirectionalLightSettings(settings) {
|
|
|
1271
1510
|
intensity: Math.max(0, readFiniteNumber(settings?.intensity, 2)),
|
|
1272
1511
|
direction: readVector3(settings?.direction, { x: -0.3, y: -1, z: -0.2 }),
|
|
1273
1512
|
diffuseColor: readProjectionColor(settings?.diffuseColor, { r: 1, g: 1, b: 1 }),
|
|
1513
|
+
helperVisible: settings?.helperVisible !== false,
|
|
1274
1514
|
};
|
|
1275
1515
|
}
|
|
1276
1516
|
function readProjectionHemisphericLightSettings(settings) {
|
|
@@ -1279,6 +1519,7 @@ function readProjectionHemisphericLightSettings(settings) {
|
|
|
1279
1519
|
intensity: Math.max(0, readFiniteNumber(settings?.intensity, 0.8)),
|
|
1280
1520
|
diffuseColor: readProjectionColor(settings?.diffuseColor, { r: 1, g: 1, b: 1 }),
|
|
1281
1521
|
groundColor: readProjectionColor(settings?.groundColor, { r: 0.48, g: 0.52, b: 0.62 }),
|
|
1522
|
+
helperVisible: settings?.helperVisible !== false,
|
|
1282
1523
|
};
|
|
1283
1524
|
}
|
|
1284
1525
|
function readProjectionColor(value, fallback) {
|