@volter/game-editor 0.5.65
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/BUNDLED_NOTICES +11228 -0
- package/LICENSE +686 -0
- package/LICENSE-BLENDER +1409 -0
- package/LICENSE-MCP +21 -0
- package/NOTICE +21 -0
- package/catalog/entries/audio.json +14 -0
- package/catalog/entries/bake.json +36 -0
- package/catalog/entries/blender.json +17 -0
- package/catalog/entries/react-root.json +24 -0
- package/catalog/entries/reflections.json +29 -0
- package/catalog/entries/static-batch.json +25 -0
- package/catalog/project-source/LICENSE +37 -0
- package/catalog/project-source/src/contributions/bake.kind.ts +40 -0
- package/catalog/project-source/src/contributions/builder-document.tsx +65 -0
- package/catalog/project-source/src/contributions/builder-state.ts +27 -0
- package/catalog/project-source/src/contributions/builder-ui.tsx +61 -0
- package/catalog/project-source/src/contributions/module-source.ts +502 -0
- package/catalog/project-source/src/contributions/pages.finder.ts +61 -0
- package/catalog/project-source/src/lib/audio/sfx.ts +255 -0
- package/catalog/project-source/src/lib/bake/asset-seed.ts +128 -0
- package/catalog/project-source/src/lib/bake/bake-schema.ts +65 -0
- package/catalog/project-source/src/lib/bake/clip-layering.ts +203 -0
- package/catalog/project-source/src/lib/bake/gltf-bake.ts +657 -0
- package/catalog/project-source/src/lib/bake/mesh-slice.ts +157 -0
- package/catalog/project-source/src/lib/bake/node-image.ts +463 -0
- package/catalog/project-source/src/lib/bake/object3d-bake.ts +121 -0
- package/catalog/project-source/src/lib/bake/object3d-lifecycle.ts +15 -0
- package/catalog/project-source/src/lib/bake/object3d-source.ts +8 -0
- package/catalog/project-source/src/lib/bake/params.ts +75 -0
- package/catalog/project-source/src/lib/bake/rest-relative-animation.ts +217 -0
- package/catalog/project-source/src/lib/bake/use-model.ts +95 -0
- package/catalog/project-source/src/lib/react-root/index.ts +20 -0
- package/catalog/project-source/src/lib/react-root/react-root-adapter.tsx +57 -0
- package/catalog/project-source/src/lib/reflections/ReflectionProbe.tsx +201 -0
- package/catalog/project-source/src/lib/reflections/index.ts +19 -0
- package/catalog/project-source/src/lib/reflections/probe-controller.ts +75 -0
- package/catalog/project-source/src/lib/reflections/reflection-probe-registry.ts +402 -0
- package/catalog/project-source/src/lib/reflections/volume-reflection-material.ts +416 -0
- package/catalog/project-source/src/lib/static-batch/Frozen.tsx +91 -0
- package/catalog/project-source/src/lib/static-batch/freeze.ts +579 -0
- package/catalog/project-source/src/lib/static-batch/index.ts +44 -0
- package/catalog/project-source/src/lib/static-batch/mutation-watch.ts +149 -0
- package/catalog/project-source/src/lib/static-batch/shadow-cache.ts +171 -0
- package/catalog/project-source/src/tools/bake-module.tool.ts +139 -0
- package/catalog/project-source/src/tools/bake-preview.tool.ts +475 -0
- package/dist/.vite/manifest.json +8304 -0
- package/dist/assets/AssetBudgetPanel-J9--TZPU.js +23 -0
- package/dist/assets/AudioViewer-CR7333fe.js +1 -0
- package/dist/assets/BVHLoader-6bQIXhMX.js +1 -0
- package/dist/assets/BufferGeometryUtils-Nz37EVXf.js +1 -0
- package/dist/assets/CCDIKSolver-CD7vLpsK.js +1 -0
- package/dist/assets/CSS3DRenderer-CL7ABLVK.js +1 -0
- package/dist/assets/CanvasSceneViewport-Bpi6gVTC.js +1 -0
- package/dist/assets/ColladaLoader-aVOPIsCh.js +3 -0
- package/dist/assets/ColorInput-DQBNrW-K.js +1 -0
- package/dist/assets/ConvexGeometry-CAzXlPVG.js +1 -0
- package/dist/assets/ConvexHull-BINCESFp.js +1 -0
- package/dist/assets/CopyShader-BzTUYzf6.js +24 -0
- package/dist/assets/DecalGeometry-160KRdfg.js +1 -0
- package/dist/assets/EXRLoader-Cdans_oJ.js +1 -0
- package/dist/assets/EffectComposer-DQxfsXBZ.js +1 -0
- package/dist/assets/EntityModelDocument-Ccvw66N9.js +1 -0
- package/dist/assets/EnvironmentAssetDocument-Dg-Qq6O6.js +1 -0
- package/dist/assets/FBXLoader-B4MoUtAn.js +1 -0
- package/dist/assets/Fbo-Dz-Soul3.js +1 -0
- package/dist/assets/FontLoader-CvGoVI5a.js +2 -0
- package/dist/assets/GLTFExporter-HgrCle4L.js +1 -0
- package/dist/assets/GameplaySessionTimeline-B52W3FVZ.js +1 -0
- package/dist/assets/Gltf-UHVWKz65.js +2 -0
- package/dist/assets/HDRLoader-THU88oVD.js +5 -0
- package/dist/assets/ImageViewer-Tn7s_MnW.js +1 -0
- package/dist/assets/InspectorCanvasPreview-CEr_Kxna.js +1 -0
- package/dist/assets/InspectorObjectPreview-CVejvLRg.js +1 -0
- package/dist/assets/JsonAssetDocument-C7VGcLhu.js +3 -0
- package/dist/assets/LineSegments2-CsOpKSiM.js +370 -0
- package/dist/assets/MTLLoader-_Xzd4_0p.js +2 -0
- package/dist/assets/MarchingCubes-Bsp4wrzd.js +1 -0
- package/dist/assets/MeshBVH-BiDHDcu-.js +1 -0
- package/dist/assets/ModelAssetDocument-F5GACirk.js +1 -0
- package/dist/assets/NonThreeAuthoringBootstrap-C3woOMxX.js +1 -0
- package/dist/assets/OBJLoader-BhIC6Hwo.js +5 -0
- package/dist/assets/Object3DDocumentViewport-DB7T0NTl.js +2 -0
- package/dist/assets/Object3DPreview-DL8oi7Xs.js +2 -0
- package/dist/assets/OnlineAssetDetail-C6z9RvYK.js +2 -0
- package/dist/assets/OrbitControls-CM3bPray.js +1 -0
- package/dist/assets/OrbitControls-DLpayAaK.js +1 -0
- package/dist/assets/OrthographicCamera-bQozawrh.js +1 -0
- package/dist/assets/PLYLoader-DYQqs5Ik.js +2 -0
- package/dist/assets/PerspectiveCamera-CQ2lh01o.js +1 -0
- package/dist/assets/PlayBar-BR-Vg3Jb.js +2 -0
- package/dist/assets/RGBELoader-BgBcQv8j.js +1 -0
- package/dist/assets/RectAreaLightUniformsLib-CMMoWfll.js +1 -0
- package/dist/assets/RenderPass-DPrn-Uky.js +1 -0
- package/dist/assets/ResolutionPicker-C67vs1F3.js +1 -0
- package/dist/assets/RootSelectionOverlay-BZPlxmXU.js +1 -0
- package/dist/assets/RoundedBox-BDGBg6QZ.js +1 -0
- package/dist/assets/RoundedBoxGeometry-CyUuYPfW.js +1 -0
- package/dist/assets/STLLoader-Dyv3lsxY.js +1 -0
- package/dist/assets/SelectionBox-D_75KrNW.js +1 -0
- package/dist/assets/ShaderPass-QYRpPuFJ.js +1 -0
- package/dist/assets/ShadowEditor-DkImwu1Y.js +1 -0
- package/dist/assets/SimplifyModifier-C8ayvRzd.js +1 -0
- package/dist/assets/SkeletonUtils-Cps8GOC6.js +1 -0
- package/dist/assets/Sky-CQKCgYDs.js +154 -0
- package/dist/assets/SourceAssetViewer-2SWQoUut.js +12 -0
- package/dist/assets/StageHost-BN-IoTef.js +2 -0
- package/dist/assets/StoryPreviewMount-DjyxRCXu.js +1 -0
- package/dist/assets/TDSLoader-D_T8XJ81.js +1 -0
- package/dist/assets/TextGeometry-DOWAEUV0.js +1 -0
- package/dist/assets/ThreeBoardDocument-CVncZyIq.js +2 -0
- package/dist/assets/ThreeIsolationSceneContent-C8C8whSF.js +1 -0
- package/dist/assets/ToolObject3DPreview-BRoDWe4Q.js +1 -0
- package/dist/assets/TrackballControls-DfznuQTh.js +1 -0
- package/dist/assets/TransientHint-BB1fwrvK.js +1 -0
- package/dist/assets/UnrealBloomPass-CR-cS_K5.js +83 -0
- package/dist/assets/VideoViewer-C6kocgIU.js +1 -0
- package/dist/assets/_commonjsHelpers-D6-XlEtG.js +1 -0
- package/dist/assets/active-ingest-CT6jSGhr.js +3 -0
- package/dist/assets/adapter-surface-Y37Nzcyw.js +1 -0
- package/dist/assets/after-paint-CB4bz1-e.js +1 -0
- package/dist/assets/agx-base-srgb-BjWZJgrZ.lut +0 -0
- package/dist/assets/agx-look-medium-high-contrast-D5F_ob1L.lut +0 -0
- package/dist/assets/agx-look-punchy-dxsnycNs.lut +0 -0
- package/dist/assets/animation-clock-CnjZqfJp.js +1 -0
- package/dist/assets/asset-budget-asset.menu-Di3KiQCd.js +1 -0
- package/dist/assets/asset-budget.action-DCzzcuTh.js +1 -0
- package/dist/assets/asset-budget.document-BWU8wnVW.js +1 -0
- package/dist/assets/asset-budget.menu-BGZpT_31.js +1 -0
- package/dist/assets/asset-editor-persistence-BBaONOJt.js +1 -0
- package/dist/assets/asset-loaders-BOy5Ss8k.js +2 -0
- package/dist/assets/asset-parse-error-BHMwBRU3.js +3 -0
- package/dist/assets/assets-BuSoGjBX.js +1 -0
- package/dist/assets/audio-meter-CyiToeUW.js +1 -0
- package/dist/assets/audio-unlock.service-CfUgUQVy.js +1 -0
- package/dist/assets/audio.utility-C6K6jem8.js +1 -0
- package/dist/assets/authoring-CgcOFhGS.js +1 -0
- package/dist/assets/autoplay.service-BZBGNSvt.js +1 -0
- package/dist/assets/axe-LkjAB6Lv.js +30 -0
- package/dist/assets/babylon-authoring-adapter-CL02gWDn.js +1 -0
- package/dist/assets/binding-Bmxqznjk.js +1 -0
- package/dist/assets/binding-identity-DcTpbvyg.js +1 -0
- package/dist/assets/binding-resolver-Dsh-6Vor.js +2 -0
- package/dist/assets/blender-emscripten-engine-9ZIRYNhe.js +2 -0
- package/dist/assets/blender-node-editor.document-iIDkB9sI.js +1 -0
- package/dist/assets/blender-properties-tab-C5CyPydi.js +3 -0
- package/dist/assets/blender-runtime-host-BpBwGv7r.js +4 -0
- package/dist/assets/blender-runtime-skin-DyQ9B6CR.js +7140 -0
- package/dist/assets/blender-runtime.document-lIYhhPtv.js +8 -0
- package/dist/assets/blender-timeline.document-77fx96N7.js +1 -0
- package/dist/assets/blender-uv-editor.document-fsT7B4gV.js +1 -0
- package/dist/assets/blender-version.status-o6dBm3n6.js +1 -0
- package/dist/assets/blender-wali-engine-wTOcrOMC.js +2 -0
- package/dist/assets/blender.command-BtJeWk-A.js +1 -0
- package/dist/assets/blender.keymap-GAQgeklK.js +1 -0
- package/dist/assets/blender.status-ujwGU6dU.js +1 -0
- package/dist/assets/blender.style-Dcem5f_T.js +1 -0
- package/dist/assets/board-guides-DziKSTss.js +1 -0
- package/dist/assets/body-marks-h_xDxiDE.js +1 -0
- package/dist/assets/bridge.command-o5gDNEwa.js +3 -0
- package/dist/assets/browserAll-DeWblVez.js +1 -0
- package/dist/assets/build-profiles.document-kW8iw8Xj.js +2 -0
- package/dist/assets/build-progress.status-BNRLytg2.js +1 -0
- package/dist/assets/build-session-C_sg3CEn.js +9 -0
- package/dist/assets/build.action-lYjTLb7K.js +1 -0
- package/dist/assets/build.command-DIGgUPU_.js +1 -0
- package/dist/assets/build.header-CKajx5U3.js +1 -0
- package/dist/assets/build.menu-BdU0QXny.js +1 -0
- package/dist/assets/build.service-CbBAyeu3.js +1 -0
- package/dist/assets/bus-mixer-CGfWDP3C.js +1 -0
- package/dist/assets/camera-KEsKvOL7.js +1 -0
- package/dist/assets/camera-runtime.inspector-B7unX4g1.js +1 -0
- package/dist/assets/canvas-entry-runtime-SfBxaR9M.js +2 -0
- package/dist/assets/capability-coverage-Czas4C18.js +7 -0
- package/dist/assets/chrome-trace-YZHMz60-.js +1 -0
- package/dist/assets/client-DNXj_opT.js +25 -0
- package/dist/assets/clip-planes-CnAI6DZn.js +1 -0
- package/dist/assets/collaboration-presence-DLoZ7EA3.js +1 -0
- package/dist/assets/collider-Bw0mXlsW.js +1 -0
- package/dist/assets/collider-dimensions-9xoFADXN.js +1 -0
- package/dist/assets/collision-system-DpNUJRJ3.js +1 -0
- package/dist/assets/command-results-CUQD49AB.js +1 -0
- package/dist/assets/component-board-registry-DrIa2csL.js +1 -0
- package/dist/assets/component-board.service-DCwcUssB.js +2 -0
- package/dist/assets/component-board.service-DidCyM4O.js +2 -0
- package/dist/assets/component-verbs.command-7xzfjGMZ.js +1 -0
- package/dist/assets/component-verbs.service-Bv9jId3q.js +1 -0
- package/dist/assets/config-CEZk921y.js +6 -0
- package/dist/assets/configurations-DTBMdaTL.js +1 -0
- package/dist/assets/connection.status-BifnQdOs.js +1 -0
- package/dist/assets/console-bridge-CHcb-xk5.js +1 -0
- package/dist/assets/constraint-De8f1Uiq.js +1 -0
- package/dist/assets/constraints.inspector-B9U9Yj-u.js +1 -0
- package/dist/assets/countdown-timer-CUm74dom.js +1 -0
- package/dist/assets/coverage.service-VTX5Mcsx.js +3 -0
- package/dist/assets/crash-null-boundary-v3a0uEgw.js +1 -0
- package/dist/assets/create-runtime-CVCc1BDx.js +1 -0
- package/dist/assets/curve-7Q79VgU4.js +1 -0
- package/dist/assets/data-asset-4hjS642k.js +5 -0
- package/dist/assets/data-check-core-CQEjuFyt.js +1 -0
- package/dist/assets/data-ref-CQI28C0D.js +1 -0
- package/dist/assets/debug-bridge-CCohG-d-.js +1 -0
- package/dist/assets/debug-registry-Dgvitx8M.js +1 -0
- package/dist/assets/defaults-DKiBJCPN.js +1 -0
- package/dist/assets/deferred-commands-CEMmvL47.js +1 -0
- package/dist/assets/deferred-ingest-play-DCJi_Pgu.js +2 -0
- package/dist/assets/design-time-layers-wYgOTgni.js +1 -0
- package/dist/assets/design-time-mount-registry-DUpXCg1U.js +1 -0
- package/dist/assets/design-time-mount.service-BzY21e1F.js +2 -0
- package/dist/assets/design-time-react-mount-DM9WLrF2.js +1 -0
- package/dist/assets/dev-build-gDYrq68M.js +1 -0
- package/dist/assets/directional-shadow-fit-BVkOKAv2.js +1 -0
- package/dist/assets/document-preview-three-Kbg2GCLm.js +1 -0
- package/dist/assets/dom-authoring-adapter-CY8C7f4T.js +1 -0
- package/dist/assets/draco3d-BBUTcNkz.js +1 -0
- package/dist/assets/draco_decoder-DsQ12WqX.wasm +0 -0
- package/dist/assets/draco_encoder-2Tcju8Ns.wasm +0 -0
- package/dist/assets/edit-mode-audio.service-Bzetwd5B.js +1 -0
- package/dist/assets/edit-mode-authoring-B47TfLqu.js +1 -0
- package/dist/assets/edit-mode-networking.service-YCX6RRb_.js +1 -0
- package/dist/assets/editor-api-BoJIcyZG.js +1 -0
- package/dist/assets/editor-port-C_FeBdeV.js +1 -0
- package/dist/assets/editor-presentation-activity-C7SNSmTd.js +1 -0
- package/dist/assets/entry-adjudication-Cq8Yeb74.js +1 -0
- package/dist/assets/environment-capture-7himRh2L.js +1 -0
- package/dist/assets/esbuild-BHljloGq.wasm +0 -0
- package/dist/assets/events-156d8d12.esm-ErOhDXXB.js +36 -0
- package/dist/assets/extend-B-eOccUm.js +36 -0
- package/dist/assets/extends-CF3RwP-h.js +1 -0
- package/dist/assets/eyedropper-session-bjPXnfeX.js +1 -0
- package/dist/assets/fflate.module-DPuTF8aG.js +6 -0
- package/dist/assets/filmic-srgb-Ct35FIH6.lut +0 -0
- package/dist/assets/first-party-audio-system-DxnGJOER.js +1 -0
- package/dist/assets/first-party-navigation-system-CL5Bquub.js +1 -0
- package/dist/assets/fork-menu-BoVyw2Wu.js +1 -0
- package/dist/assets/frame-debugger-store-D1Mf_5up.js +1 -0
- package/dist/assets/frame-delta-D2nsw_Ht.js +1 -0
- package/dist/assets/frame-pacing-D5acoOzO.js +1 -0
- package/dist/assets/frame-selector-cache-cCeUbcjG.js +1 -0
- package/dist/assets/game-DHOZVb-7.js +1 -0
- package/dist/assets/game-contract-seams-a5YXejOu.js +1 -0
- package/dist/assets/game-css-scope-transform-Eng4wS8E.js +33 -0
- package/dist/assets/game-document.service-DbRfx2V0.js +1 -0
- package/dist/assets/game-eval.command-D-7Dxbj_.js +2 -0
- package/dist/assets/game-input-seams-CIQdetRw.js +1 -0
- package/dist/assets/game-loop-CZvXlY00.js +1 -0
- package/dist/assets/game-module-access-B2mFxv-i.js +1 -0
- package/dist/assets/game.layout-CBASrvQu.js +1 -0
- package/dist/assets/gameplay-export-BoKXm51x.js +1 -0
- package/dist/assets/gameplay-replay-e5umMlXv.js +1 -0
- package/dist/assets/gameplay-rng-trap-CTNhm-UW.js +3 -0
- package/dist/assets/gameplay.command-DxcVYX6F.js +1 -0
- package/dist/assets/generation-DhwCUHPf.css +1 -0
- package/dist/assets/generation-jobs-BQrXbGp_.js +1 -0
- package/dist/assets/generation.service-CDIgObuw.js +1 -0
- package/dist/assets/generations-DzUogZsM.js +1 -0
- package/dist/assets/generations.status-CgOUBCum.js +1 -0
- package/dist/assets/hierarchy-marks-BLPfSIym.js +1 -0
- package/dist/assets/host-pointer-DbGSCjE9.js +1 -0
- package/dist/assets/hosted-asset-materialization-CiIvWkGU.js +2 -0
- package/dist/assets/ibl-override-material-BlmCxFKq.js +6 -0
- package/dist/assets/index-96FBF1Oj.js +1 -0
- package/dist/assets/index-BAWkB0dv.js +1 -0
- package/dist/assets/index-BDnS2b6S.js +1 -0
- package/dist/assets/index-BHp07vN0.js +2 -0
- package/dist/assets/index-BMxv2MNV.js +1 -0
- package/dist/assets/index-BP6wv2A0.js +5 -0
- package/dist/assets/index-BcCBqgM_.js +952 -0
- package/dist/assets/index-Bge9JUr6.js +1 -0
- package/dist/assets/index-BjTCPEQ7.js +134 -0
- package/dist/assets/index-BncK9THk.js +1 -0
- package/dist/assets/index-CJbYy-CF.js +3 -0
- package/dist/assets/index-CVCb_ImQ.js +1 -0
- package/dist/assets/index-CZd9o7Lu.js +1 -0
- package/dist/assets/index-CanA16PU.js +2 -0
- package/dist/assets/index-CinJrH5C.js +9 -0
- package/dist/assets/index-CtzuWnCS.js +1 -0
- package/dist/assets/index-D2fNXpHa.css +1 -0
- package/dist/assets/index-DUpHH6JR.js +3120 -0
- package/dist/assets/index-DUqP1RMl.js +1 -0
- package/dist/assets/index-D_NuPfjr.js +9 -0
- package/dist/assets/index-Da9JhEvW.js +25 -0
- package/dist/assets/index-DgapqSPi.js +7 -0
- package/dist/assets/index-FUuS4qwW.js +562 -0
- package/dist/assets/index-GIL7oGEO.js +4894 -0
- package/dist/assets/index-IEjydI9d.js +1 -0
- package/dist/assets/index-OrYXPk3Z.js +487 -0
- package/dist/assets/index-V1R-e5Bd.js +1 -0
- package/dist/assets/index-bQE2NA0D.js +1 -0
- package/dist/assets/index-gHZae-lw.js +13 -0
- package/dist/assets/index-mjWQmGhM.js +1 -0
- package/dist/assets/index-nmcBqr7Y.js +1 -0
- package/dist/assets/inference-diagnostics-Dhmtfbq_.js +1 -0
- package/dist/assets/ingest-BbYMC2vQ.js +1 -0
- package/dist/assets/ingest-boot-viewport-D5rI_Kk_.js +1 -0
- package/dist/assets/ingest-siblings-Bop2kqVl.js +1 -0
- package/dist/assets/ingest-source-persistence-C_6Hiyra.js +1 -0
- package/dist/assets/ingest.service-BTDnQfM1.js +1 -0
- package/dist/assets/input-manager-DH_hGW6d.js +1 -0
- package/dist/assets/input-router-BNQvtIqw.js +1 -0
- package/dist/assets/inspect-BZfi3mmo.js +1 -0
- package/dist/assets/inspection-CObLhnrs.js +1 -0
- package/dist/assets/instance-fork-actions-D3sRzS3K.js +1 -0
- package/dist/assets/instances.command-D6UkZNO8.js +1 -0
- package/dist/assets/instruments-CKR02Y8I.js +1 -0
- package/dist/assets/json-history-resource-BbxllWfV.js +1 -0
- package/dist/assets/jsx-runtime-DPjLkJKQ.js +9 -0
- package/dist/assets/light-D-_wsKTq.js +1 -0
- package/dist/assets/light-camera-factory-CWbbe9gI.js +1 -0
- package/dist/assets/lil-gui.module.min-BF55BEwA.js +10 -0
- package/dist/assets/live-behaviors-Bxq49Maz.js +1 -0
- package/dist/assets/live-gesture-lock-DJbrjOqf.js +1 -0
- package/dist/assets/loader-CaF_I7Yt.js +1 -0
- package/dist/assets/logger-Dqis-7W1.js +1 -0
- package/dist/assets/loop-gate-report-N52EWFGD.js +1 -0
- package/dist/assets/matcap-texture-CVfalpWT.js +1 -0
- package/dist/assets/material-CpAdjDxn.js +1 -0
- package/dist/assets/material-factory-Bz6h__6g.js +1 -0
- package/dist/assets/mesh-B3WPtNKO.js +1 -0
- package/dist/assets/mesh-shadow-CZnXrw_l.js +1 -0
- package/dist/assets/mikktspace.module-DO88SLib.js +1 -0
- package/dist/assets/model-asset-sections-CFvvihfx.css +1 -0
- package/dist/assets/model-asset-sections.service-CHhFS3ZX.js +1 -0
- package/dist/assets/model.layout-BJUEQYUI.js +1 -0
- package/dist/assets/models.finder-G2jQgIRu.js +1 -0
- package/dist/assets/module-mode-DVBLT9d-.js +2 -0
- package/dist/assets/mount-canvas-ingest-root-DDuAWf_C.js +2 -0
- package/dist/assets/mount-dom-ingest-root-D_EiBgpn.js +2 -0
- package/dist/assets/mount-game-6t9cKNo4.js +1 -0
- package/dist/assets/mount-ingest-root-glv2SSWf.js +2 -0
- package/dist/assets/mount-manifest-CGVxhmAw.js +1 -0
- package/dist/assets/mount-readiness-Ds0HvvLH.js +4 -0
- package/dist/assets/mount-three-ingest-root-hrUt9VVU.js +1 -0
- package/dist/assets/mounted-authoring-Dmg5xmhP.js +1 -0
- package/dist/assets/mounted-story-viewport-source-DjP6RA9U.js +1 -0
- package/dist/assets/native-debug-module-CWicoSGD.js +1 -0
- package/dist/assets/native-entry-surface-BE8LJNdu.js +1 -0
- package/dist/assets/navigation-CIiCx-SM.js +1 -0
- package/dist/assets/navmesh-workflow-store-Cmnm57TB.js +1 -0
- package/dist/assets/navmesh.menu-CAKiH8PW.js +1 -0
- package/dist/assets/navmesh.service-jgDWlgj1.js +1 -0
- package/dist/assets/network.utility-CEu5nHf7.js +1 -0
- package/dist/assets/object-marks-DwvIEBOK.js +1 -0
- package/dist/assets/object3d-authoring-subject-CH5sI2oP.js +1 -0
- package/dist/assets/output-DK8waum9.js +195 -0
- package/dist/assets/particles-Y626p22p.js +1 -0
- package/dist/assets/particles-factory-DnLOHXT8.js +1 -0
- package/dist/assets/pasteboard-materialize-BqSS4QzV.js +20 -0
- package/dist/assets/pasteboard.action-DU3UHtJG.js +2 -0
- package/dist/assets/performance-profiler-D_Jey87L.js +1 -0
- package/dist/assets/physics-registry-B2Jkp8e6.js +1 -0
- package/dist/assets/physics-registry-CUB9cT9p.js +1 -0
- package/dist/assets/pixi-authoring-adapter-CjibysC3.js +1 -0
- package/dist/assets/pixi-live-write-target-DuWydlWb.js +1 -0
- package/dist/assets/pixi-primitive-DlWbUPN9.js +1 -0
- package/dist/assets/pixi-react-root-factory-DYsznYRQ.js +1 -0
- package/dist/assets/pixi-story-model-DNkfnWUV.js +1 -0
- package/dist/assets/pixi-transform-channels-VjdohT11.js +1 -0
- package/dist/assets/play-mode-BFU2PCkG.js +22 -0
- package/dist/assets/play.command-BpqqLqkq.js +2 -0
- package/dist/assets/playtest-BXIL1JEF.js +1 -0
- package/dist/assets/pose-guard-6Osb2cFu.js +1 -0
- package/dist/assets/presentation-BPP5pXeQ.js +1 -0
- package/dist/assets/product-DFhyARJj.js +1 -0
- package/dist/assets/profiler.action-CaXJDp3t.js +1 -0
- package/dist/assets/profiler.menu-BIMF6Bi4.js +1 -0
- package/dist/assets/profiler.utility-BExw9wBO.js +1 -0
- package/dist/assets/project-authoring-session-Bnt6icLr.js +2 -0
- package/dist/assets/project-provenance-BoP3nrle.js +1 -0
- package/dist/assets/prompt-labels-DSMdM2_B.js +1 -0
- package/dist/assets/properties-bone-constraints.inspector-ByT6p7S-.js +1 -0
- package/dist/assets/properties-bone.inspector-z4qJwKO5.js +1 -0
- package/dist/assets/properties-collection.inspector-D0_3ijWU.js +1 -0
- package/dist/assets/properties-constraints.inspector-CESzjuls.js +1 -0
- package/dist/assets/properties-data.inspector-hG8Wgyzb.js +1 -0
- package/dist/assets/properties-material.inspector-CzY0JCQ6.js +1 -0
- package/dist/assets/properties-modifiers.inspector-3dDhwf7g.js +1 -0
- package/dist/assets/properties-object.inspector-CiarfxkT.js +1 -0
- package/dist/assets/properties-output.inspector-DKJxmKSD.js +1 -0
- package/dist/assets/properties-particles.inspector-CCEdYWGm.js +1 -0
- package/dist/assets/properties-physics.inspector-B2c0KUyA.js +1 -0
- package/dist/assets/properties-render.inspector-Bcm0HLRW.js +1 -0
- package/dist/assets/properties-scene.inspector-PIM_eTb_.js +1 -0
- package/dist/assets/properties-texture.inspector-CgFlnyr8.js +1 -0
- package/dist/assets/properties-view-layer.inspector-DGjF_Aqo.js +1 -0
- package/dist/assets/properties-world.inspector-CrMvaRvB.js +1 -0
- package/dist/assets/r3f-design-session-D-4yyDO9.js +2 -0
- package/dist/assets/r3f-physics-binding-BBo8oma9.js +1 -0
- package/dist/assets/r3f-root-factory-z9llD1OU.js +1 -0
- package/dist/assets/r3f-source-authoring-adapter-w6Bc60K-.js +13 -0
- package/dist/assets/rapier-physics-adapter-CaZqWLu0.js +1 -0
- package/dist/assets/rapier-physics-bridge-CMoeVo3Y.js +1 -0
- package/dist/assets/react-18-By2b4xR9.js +1 -0
- package/dist/assets/react-inspector.service-B_neRnSK.js +1 -0
- package/dist/assets/react-root-CEz5NTck.js +1 -0
- package/dist/assets/react-story-board-BDDwiE2H.js +1 -0
- package/dist/assets/react-three-fiber.esm-CycrbDlA.js +1 -0
- package/dist/assets/react-three-rapier.esm-CEfKpvxT.js +1 -0
- package/dist/assets/react-world-authoring-adapter-DmrwM3py.js +1 -0
- package/dist/assets/realm-services-CobQsq_X.js +1 -0
- package/dist/assets/rebind-controller-Dtq19Vb3.js +1 -0
- package/dist/assets/recast-navigation.wasm-compat-Dsoa_MD-.js +1 -0
- package/dist/assets/reflection-probe-Don-M3Fj.js +1 -0
- package/dist/assets/reflection-probe-capture.inspector-CmFUoJCx.js +1 -0
- package/dist/assets/register-render-vitals-BiZk29b2.js +1 -0
- package/dist/assets/registry-02YZjMNp.js +1 -0
- package/dist/assets/relative-path-guard-GiM7Lsz8.js +1 -0
- package/dist/assets/render-audio-control-vMRlePWb.js +1 -0
- package/dist/assets/render-batch-system-0vq7p0VC.js +1 -0
- package/dist/assets/render-census-BrQX_CXv.js +1 -0
- package/dist/assets/render-control-Df3yTiyr.js +1 -0
- package/dist/assets/render-env-D2IV2x5k.js +1 -0
- package/dist/assets/render-features-CPQ_e568.js +1 -0
- package/dist/assets/render-seed-DF4JHy7P.js +1 -0
- package/dist/assets/render-settings-Bw4W9SYF.js +1 -0
- package/dist/assets/render-vitals-BZ5HtvMi.js +1 -0
- package/dist/assets/renderer-config-BqG4O8i9.js +1 -0
- package/dist/assets/resolve-three-SZE_WWUM.js +702 -0
- package/dist/assets/root-seam-contract-Z0VWX3Bk.js +1 -0
- package/dist/assets/rrweb-Cd2ifIRP.js +142 -0
- package/dist/assets/run-ticks-settled-C4ksViyA.js +1 -0
- package/dist/assets/runtime-inspection-l2iFQSsg.js +1 -0
- package/dist/assets/scene-capture-BQKzU0NT.js +1 -0
- package/dist/assets/scene-capture-CGYF-Viw.js +1 -0
- package/dist/assets/scene-document.service-qkDjUrlP.js +2 -0
- package/dist/assets/scene-framing-Cat0GtyJ.js +1 -0
- package/dist/assets/scene-index-B6BZOHMk.js +1 -0
- package/dist/assets/scene-query-C7_N-TpI.js +1 -0
- package/dist/assets/schema-kl9-2B_J.js +1 -0
- package/dist/assets/sculpt.layout-zJF55yCR.js +1 -0
- package/dist/assets/seeded-random-i3mtgBKZ.js +1 -0
- package/dist/assets/session-CZ5JPg-z.js +4877 -0
- package/dist/assets/setup-audio-S8GQF91f.js +1 -0
- package/dist/assets/setup-particles-GCXlnkj_.js +1 -0
- package/dist/assets/setup-physics-BeZ7-LKD.js +1 -0
- package/dist/assets/setup-renderer-DVXaSGin.js +1587 -0
- package/dist/assets/shading.layout-DULYZV6M.js +1 -0
- package/dist/assets/sim-clock-CLflx7kg.js +1 -0
- package/dist/assets/sky-precompute-worker-ChN7J87v.js +1 -0
- package/dist/assets/soft-particle-depth-DGvfQDi1.js +1 -0
- package/dist/assets/source-object3d-authoring-adapter-B-L6Ha6f.js +1 -0
- package/dist/assets/source-persistence-backend-C-aR-B_Y.js +1 -0
- package/dist/assets/spark-renderer-lifecycle-ynWESJcv.js +1 -0
- package/dist/assets/spark.module-4pXQoz5d.js +12120 -0
- package/dist/assets/stage-invalidation-DBg3C3Ta.js +1 -0
- package/dist/assets/stage-keyboard-n-5kKH-m.js +1 -0
- package/dist/assets/stage-overlay-set-B9zp2sLB.js +1 -0
- package/dist/assets/stage-presence-markers-DiGI6A45.js +1 -0
- package/dist/assets/standard-viewport-dressing-CzjAe_0A.js +7 -0
- package/dist/assets/state-bridge-DLP1jLRW.js +1 -0
- package/dist/assets/state-watch.action-BOvQR2qt.js +1 -0
- package/dist/assets/state-watch.menu-CNLvDeeY.js +1 -0
- package/dist/assets/state-watch.utility-Bg1tTTQU.js +1 -0
- package/dist/assets/static-batch-advisor-B13QEH7d.js +1 -0
- package/dist/assets/stats.module-BL02l9NC.js +1 -0
- package/dist/assets/story-arg-descriptors-Ek86ExX7.js +1 -0
- package/dist/assets/story-capture-_gC8dXV-.js +1 -0
- package/dist/assets/story-documents--TDLaPeL.js +3 -0
- package/dist/assets/story-documents.service-BiS_YbNQ.js +1 -0
- package/dist/assets/story-documents.service-CxOPYJ2j.js +1 -0
- package/dist/assets/story-media-presence-BHzk2IV5.js +1 -0
- package/dist/assets/story-mount-turn-DFRTj5hi.js +1 -0
- package/dist/assets/story-pixi-preview-BUrOJZXS.js +1 -0
- package/dist/assets/story-presentation-j2AVN-mK.js +1 -0
- package/dist/assets/story-three-preview-BHEDZzcl.js +2 -0
- package/dist/assets/structural-ids-Dc-7rEwi.js +1 -0
- package/dist/assets/structural-signature-0w-i_ats.js +1 -0
- package/dist/assets/surface-content-Dg9Kkazf.js +1 -0
- package/dist/assets/surface-state-DaxyruCj.js +3 -0
- package/dist/assets/system-adapters-rIC8FSGP.js +1 -0
- package/dist/assets/system-runner-DkOjxEBt.js +1 -0
- package/dist/assets/system-slot-E2mEdiih.js +1 -0
- package/dist/assets/team-playtest.service-DqOinFVA.js +1 -0
- package/dist/assets/texture.layout-DASpHVht.js +1 -0
- package/dist/assets/three-CDSueJyJ.js +1 -0
- package/dist/assets/three-authoring-adapter-CmSQ3Vui.js +1 -0
- package/dist/assets/three-authoring.service-iuHLwtf1.js +2 -0
- package/dist/assets/three-ingest-runtime-QzDYk6tU.js +1 -0
- package/dist/assets/three-projection-core-BmKMZ-nf.js +1 -0
- package/dist/assets/three-viewport-presentation-QBQpSdMh.js +1 -0
- package/dist/assets/three.module-D396a9Mn.js +3840 -0
- package/dist/assets/three.quarks.esm-B1C61jGo.js +1039 -0
- package/dist/assets/tools-B_NJsk05.js +1 -0
- package/dist/assets/transform-writer-BhBBTx33.js +1 -0
- package/dist/assets/transport.header-B-6HQlU2.js +1 -0
- package/dist/assets/trigger-volume-BNK2XzPL.js +1 -0
- package/dist/assets/tuples-CIQ4Bn1U.js +1 -0
- package/dist/assets/tween.module-DciWpAG6.js +1 -0
- package/dist/assets/ui-board-document-Bwtt--xp.js +2 -0
- package/dist/assets/unexported-game-trap-Dm1JYKHy.js +2 -0
- package/dist/assets/unmanaged-root-detector-B8CpbkSN.js +2 -0
- package/dist/assets/upstream-pin-BdgRH6ID.js +1 -0
- package/dist/assets/use-data-Dzq-MytE.js +1 -0
- package/dist/assets/use-live-actor-state-DErbWQWF.js +1 -0
- package/dist/assets/use-selection-DbR73-xd.js +1 -0
- package/dist/assets/user-data-BB2Of6Ht.js +1 -0
- package/dist/assets/utility-view-state-BHypxA33.js +1 -0
- package/dist/assets/uv-editing.layout-BEKHxmHw.js +1 -0
- package/dist/assets/vgai-shared-fontawesome-CU65D4Ij.js +1 -0
- package/dist/assets/vgai-shared-jsx-dev-runtime-DFDKL7fx.js +1 -0
- package/dist/assets/vgai-shared-jsx-runtime-DIqBpTut.js +1 -0
- package/dist/assets/vgai-shared-react-BT7rMc2H.js +1 -0
- package/dist/assets/vgai-shared-react-dom-DFajMqMT.js +1 -0
- package/dist/assets/vgai-shared-react-dom-client-S0ozfl6_.js +1 -0
- package/dist/assets/vgai-shared-three-Bc5PvpLM.js +1 -0
- package/dist/assets/viewport-pick-context-DkawXbEi.js +1 -0
- package/dist/assets/viewport-root-presentation-CWsE56K6.js +1 -0
- package/dist/assets/viewport-shading-BuA88e_A.js +1 -0
- package/dist/assets/viewport-shading-boundary-B_-_gABg.js +82 -0
- package/dist/assets/viewport-surface-status-B3om4Kcf.js +1 -0
- package/dist/assets/vision_bundle-DX0dWqEa.js +15 -0
- package/dist/assets/voxel-surface-DtcsSWRL.js +1 -0
- package/dist/assets/wav-encode-D31zWF6O.js +1 -0
- package/dist/assets/webgl-frame-capture-FlF9zQmW.js +1 -0
- package/dist/assets/webgl-gpu-timer-D3YX7RaD.js +1 -0
- package/dist/assets/webworkerAll-CM2o_dnz.js +1 -0
- package/dist/assets/worker-UrMcrc5_.js +2 -0
- package/dist/assets/world-documents-147tiFZe.js +1 -0
- package/dist/assets/world-root-stage-binding-vwTrtBz6.js +1 -0
- package/dist/assets/world-state-BWG-IcOd.js +1 -0
- package/dist/assets/writer-B-KovzkA.js +5 -0
- package/dist/assets/xstate-animation-binding-Brd0NST6.js +1 -0
- package/dist/assets/xstate-animation-meta-Q3u9zh_m.js +1 -0
- package/dist/assets/xstate-behavior.action-B8UluFBK.js +1 -0
- package/dist/assets/xstate-behavior.document-CKAsE45I.js +1 -0
- package/dist/assets/xstate-behavior.inspector-vJJyuifc.js +1 -0
- package/dist/assets/xstate-behavior.menu-BXbPICIh.js +1 -0
- package/dist/assets/xstate-inspection-BsZv8LS9.js +1 -0
- package/dist/vgai-shared-react.json +10 -0
- package/dist/vgai-shared-three.json +3 -0
- package/dist-node/cli.js +9320 -0
- package/dist-node/create.js +3239 -0
- package/package.json +91 -0
- package/presets.mjs +2 -0
- package/src/contributions.d.ts +4 -0
- package/src/index.ts +38 -0
- package/starter/cube.blend +0 -0
- package/starter/cube.py +81 -0
- package/template/.agents/references/project-manual.md +341 -0
- package/template/.agents/skills/editor/SKILL.md +53 -0
- package/template/.agents/skills/editor/agents/openai.yaml +4 -0
- package/template/.agents/skills/editor/references/editor-control.md +363 -0
- package/template/.agents/skills/vgai-3d-models/SKILL.md +64 -0
- package/template/.agents/skills/vgai-ingest-existing-game/SKILL.md +112 -0
- package/template/.agents/skills/vgai-threejs-authoring/SKILL.md +347 -0
- package/template/.agents/skills/vgai-threejs-authoring/agents/openai.yaml +4 -0
- package/template/.agents/skills/vgai-threejs-authoring/references/helper-catalog.md +65 -0
- package/template/.claude/skills/editor/SKILL.md +53 -0
- package/template/.claude/skills/editor/agents/openai.yaml +4 -0
- package/template/.claude/skills/editor/references/editor-control.md +363 -0
- package/template/.claude/skills/vgai-3d-models/SKILL.md +64 -0
- package/template/.claude/skills/vgai-ingest-existing-game/SKILL.md +112 -0
- package/template/.claude/skills/vgai-threejs-authoring/SKILL.md +347 -0
- package/template/.claude/skills/vgai-threejs-authoring/agents/openai.yaml +4 -0
- package/template/.claude/skills/vgai-threejs-authoring/references/helper-catalog.md +65 -0
- package/template/.github/copilot-instructions.md +6 -0
- package/template/.github/skills/editor/SKILL.md +53 -0
- package/template/.github/skills/editor/agents/openai.yaml +4 -0
- package/template/.github/skills/editor/references/editor-control.md +363 -0
- package/template/.github/skills/vgai-3d-models/SKILL.md +64 -0
- package/template/.github/skills/vgai-ingest-existing-game/SKILL.md +112 -0
- package/template/.github/skills/vgai-threejs-authoring/SKILL.md +347 -0
- package/template/.github/skills/vgai-threejs-authoring/agents/openai.yaml +4 -0
- package/template/.github/skills/vgai-threejs-authoring/references/helper-catalog.md +65 -0
- package/template/.mcp.json +12 -0
- package/template/.vgai/assets.json +1 -0
- package/template/.vgai/provenance.json +4 -0
- package/template/.volter/tracker/validation/.preset.base.mts +178 -0
- package/template/.volter/tracker/validation/preset.mts +186 -0
- package/template/.volter/tracker/visualizer/.extension.base.tsx +14 -0
- package/template/.volter/tracker/visualizer/extension.tsx +14 -0
- package/template/.volter/tracker-config.json +17 -0
- package/template/AGENTS.md +176 -0
- package/template/CLAUDE.md +1 -0
- package/template/DEVLOG.md +20 -0
- package/template/IDIOMS.md +118 -0
- package/template/LICENSE +30 -0
- package/template/README.md +83 -0
- package/template/ROADMAP.md +20 -0
- package/template/asset-manifest.json +3 -0
- package/template/check-idioms.ts +1533 -0
- package/template/index.html +18 -0
- package/template/manifest-entry-modules-plugin.ts +53 -0
- package/template/package.json +62 -0
- package/template/public/jsm/libs/basis/basis_transcoder.js +19 -0
- package/template/public/jsm/libs/basis/basis_transcoder.wasm +0 -0
- package/template/public/jsm/libs/draco/gltf/draco_decoder.js +33 -0
- package/template/public/jsm/libs/draco/gltf/draco_decoder.wasm +0 -0
- package/template/public/jsm/libs/draco/gltf/draco_encoder.js +33 -0
- package/template/public/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -0
- package/template/public/shaders/daylight-sky.frag.glsl +15 -0
- package/template/public/shaders/daylight-sky.vert.glsl +7 -0
- package/template/scripts/patch-drei-stats-gl.mjs +35 -0
- package/template/server/colyseus-setup.ts +111 -0
- package/template/server/loopback.ts +76 -0
- package/template/server/main.ts +78 -0
- package/template/server/rooms/arena-room.ts +488 -0
- package/template/server/rooms/game-room.ts +274 -0
- package/template/server/rooms.ts +15 -0
- package/template/server/tsconfig.json +19 -0
- package/template/src/bot/QaTester.tsx +35 -0
- package/template/src/bot/behaviors.ts +203 -0
- package/template/src/bot/bot-station.ts +192 -0
- package/template/src/bot/tester-run.ts +238 -0
- package/template/src/bot/tester-station.ts +193 -0
- package/template/src/components/environment/DaylightSky.tsx +54 -0
- package/template/src/components/environment/Ground.tsx +129 -0
- package/template/src/components/environment/SceneAtmosphere.tsx +14 -0
- package/template/src/components/environment/SoftGroundShadow.tsx +62 -0
- package/template/src/components/environment/SunShadowFit.tsx +141 -0
- package/template/src/contributions/README.md +98 -0
- package/template/src/contributions/analytics.analytics.tsx +26 -0
- package/template/src/contributions/data.document.tsx +35 -0
- package/template/src/contributions/pages.finder.ts +61 -0
- package/template/src/contributions/tester.inspector.tsx +64 -0
- package/template/src/contributions/use-game-modules.ts +80 -0
- package/template/src/data/README.md +17 -0
- package/template/src/input.ts +97 -0
- package/template/src/lib/audio/capability.json +4 -0
- package/template/src/lib/audio/sfx.ts +255 -0
- package/template/src/lib/react-root/capability.json +4 -0
- package/template/src/lib/react-root/index.ts +20 -0
- package/template/src/lib/react-root/react-root-adapter.tsx +57 -0
- package/template/src/lib/reflections/ReflectionProbe.tsx +201 -0
- package/template/src/lib/reflections/capability.json +4 -0
- package/template/src/lib/reflections/index.ts +19 -0
- package/template/src/lib/reflections/probe-controller.ts +75 -0
- package/template/src/lib/reflections/reflection-probe-registry.ts +402 -0
- package/template/src/lib/reflections/volume-reflection-material.ts +416 -0
- package/template/src/lib/static-batch/Frozen.tsx +91 -0
- package/template/src/lib/static-batch/capability.json +4 -0
- package/template/src/lib/static-batch/freeze.ts +579 -0
- package/template/src/lib/static-batch/index.ts +44 -0
- package/template/src/lib/static-batch/mutation-watch.ts +149 -0
- package/template/src/lib/static-batch/shadow-cache.ts +171 -0
- package/template/src/main.ts +63 -0
- package/template/src/manifest-entry-modules.d.ts +3 -0
- package/template/src/prefabs/HeroBox.stories.tsx +23 -0
- package/template/src/prefabs/HeroBox.tsx +35 -0
- package/template/src/scenes/MainScene.tsx +77 -0
- package/template/src/world.tsx +87 -0
- package/template/tsconfig.json +35 -0
- package/template/tsconfig.node.json +32 -0
- package/template/tsconfig.tools.json +22 -0
- package/template/validate-asset-content.ts +27 -0
- package/template/validate-assets.ts +60 -0
- package/template/validate-manifest.ts +55 -0
- package/template/vgai.adapter.ts +76 -0
- package/template/vgai.project.json +24 -0
- package/template/vite.config.ts +247 -0
- package/template-dotfiles/gitignore +63 -0
- package/workbench/src/media/game-cover.css +83 -0
- package/workbench/src/product.contribution.ts +188 -0
- package/workbench/src/vgaiGameSkew.ts +276 -0
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The module→Object3D step, shared by every tool that turns a project TS
|
|
3
|
+
* module's exported builder into a live `THREE.Object3D`.
|
|
4
|
+
*
|
|
5
|
+
* EXTRACTED VERBATIM from `src/tools/bake-module.tool.ts` (the typed error
|
|
6
|
+
* definitions, `resolveProjectModule`, `buildFromModule` and
|
|
7
|
+
* `computeMeshStats` were private there) when `project.bake.preview` needed
|
|
8
|
+
* the identical front half without the bake. Nothing about the behavior
|
|
9
|
+
* changed: the same path-escape guard, the same import, the same typed error
|
|
10
|
+
* codes. One copy, because "the same module, refused for a different reason
|
|
11
|
+
* depending on which verb you called" is the failure this prevents.
|
|
12
|
+
*
|
|
13
|
+
* It lives beside the tools rather than under `src/lib/bake/` because it is
|
|
14
|
+
* NODE-ONLY (`node:fs/promises`, `node:url`, a dynamic `import()` of project
|
|
15
|
+
* source). A project's own `tsconfig.json` compiles `src` for the browser and
|
|
16
|
+
* excludes `src/tools` precisely so tool code can reach for Node; a helper
|
|
17
|
+
* this shape under `src/lib/` reds every shipped project's typecheck.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { realpath } from 'node:fs/promises';
|
|
21
|
+
import { resolve, sep } from 'node:path';
|
|
22
|
+
import { pathToFileURL } from 'node:url';
|
|
23
|
+
import { ToolError } from '@volter/editor-sdk/tools/errors';
|
|
24
|
+
import type { ToolErrorDefinition } from '@volter/editor-sdk/tools/registry';
|
|
25
|
+
import * as THREE from 'three';
|
|
26
|
+
import { z } from 'zod';
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Typed error codes — every real failure mode of `buildFromModule` /
|
|
30
|
+
// `resolveProjectModule`, mirroring the `ToolErrorDefinition` + `ToolError`
|
|
31
|
+
// pattern the SDK's own `project.*` operations use (e.g.
|
|
32
|
+
// `PATH_OUTSIDE_PROJECT_ERROR` in `@volter/editor-sdk`'s `project/shared.ts`).
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
export const MODULE_NOT_FOUND_ERROR: ToolErrorDefinition = {
|
|
36
|
+
code: 'MODULE_NOT_FOUND',
|
|
37
|
+
summary: 'The TypeScript module at modulePath does not exist, or failed to import.',
|
|
38
|
+
data: z.object({ modulePath: z.string(), reason: z.string() }),
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const EXPORT_NOT_CALLABLE_ERROR: ToolErrorDefinition = {
|
|
42
|
+
code: 'EXPORT_NOT_CALLABLE',
|
|
43
|
+
summary: "The named export is missing from the module, or isn't a function.",
|
|
44
|
+
data: z.object({
|
|
45
|
+
modulePath: z.string(),
|
|
46
|
+
exportName: z.string(),
|
|
47
|
+
available: z.array(z.string()),
|
|
48
|
+
}),
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const NOT_AN_OBJECT3D_ERROR: ToolErrorDefinition = {
|
|
52
|
+
code: 'NOT_AN_OBJECT3D',
|
|
53
|
+
summary: 'The export ran but did not return a THREE.Object3D or a THREE.BufferGeometry.',
|
|
54
|
+
data: z.object({ modulePath: z.string(), exportName: z.string(), returnedType: z.string() }),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const EMPTY_GEOMETRY_ERROR: ToolErrorDefinition = {
|
|
58
|
+
code: 'EMPTY_GEOMETRY',
|
|
59
|
+
summary: 'The built Object3D has zero vertices or triangles — nothing renderable to bake.',
|
|
60
|
+
data: z.object({ modulePath: z.string(), exportName: z.string() }),
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const PATH_ESCAPES_PROJECT_ERROR: ToolErrorDefinition = {
|
|
64
|
+
code: 'PATH_ESCAPES_PROJECT',
|
|
65
|
+
summary: 'modulePath resolves outside the project root (e.g. via "..").',
|
|
66
|
+
data: z.object({ projectRoot: z.string(), modulePath: z.string() }),
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/** Resolve `modulePath` to an absolute path that stays inside the project root (no `..` escape). */
|
|
70
|
+
export async function resolveProjectModule(
|
|
71
|
+
projectRoot: string,
|
|
72
|
+
modulePath: string,
|
|
73
|
+
): Promise<string> {
|
|
74
|
+
const relativePath = modulePath.replace(/^\//, '');
|
|
75
|
+
const projectRootReal = await realpath(projectRoot);
|
|
76
|
+
const lexicalCandidate = resolve(projectRootReal, relativePath);
|
|
77
|
+
if (
|
|
78
|
+
lexicalCandidate !== projectRootReal &&
|
|
79
|
+
!lexicalCandidate.startsWith(`${projectRootReal}${sep}`)
|
|
80
|
+
) {
|
|
81
|
+
throw new ToolError(
|
|
82
|
+
PATH_ESCAPES_PROJECT_ERROR.code,
|
|
83
|
+
`modulePath must resolve inside the project: ${modulePath}`,
|
|
84
|
+
{ projectRoot: projectRootReal, modulePath },
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
let candidate: string;
|
|
88
|
+
try {
|
|
89
|
+
candidate = await realpath(lexicalCandidate);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
throw new ToolError(
|
|
92
|
+
MODULE_NOT_FOUND_ERROR.code,
|
|
93
|
+
`module '${modulePath}' does not exist in the project.`,
|
|
94
|
+
{ modulePath, reason: error instanceof Error ? error.message : String(error) },
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
if (candidate !== projectRootReal && !candidate.startsWith(`${projectRootReal}${sep}`)) {
|
|
98
|
+
throw new ToolError(
|
|
99
|
+
PATH_ESCAPES_PROJECT_ERROR.code,
|
|
100
|
+
`modulePath must resolve inside the project: ${modulePath}`,
|
|
101
|
+
{ projectRoot: projectRootReal, modulePath },
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return candidate;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* THE TWO SHAPES A MODULE EXPORT MAY RETURN, normalized to one.
|
|
109
|
+
*
|
|
110
|
+
* 1. A bare `THREE.Object3D` — the original contract, and still the whole of
|
|
111
|
+
* it for a builder with nothing to tear down.
|
|
112
|
+
* 2. A BUILD RESULT `{ root, animations?, dispose? }` — the shape every
|
|
113
|
+
* parametric lib in the kit already returns (`createBird`'s `BirdBuild`,
|
|
114
|
+
* `createHumanoid`'s, and the fox/cub/winter generators a cold agent wrote
|
|
115
|
+
* from them). It is not a new convention invented here: `bakeObject3DSource`
|
|
116
|
+
* has always taken exactly `{ root, animations, dispose }` from its `build`
|
|
117
|
+
* callback, so the bake lane consumed this shape while the MODULE lane —
|
|
118
|
+
* `project.bake.module`, `project.bake.preview`, `vgai screenshot <module>`
|
|
119
|
+
* — refused it. Measured (cold fox, 2026-08-29): `vgai screenshot
|
|
120
|
+
* src/lib/fox/generate.ts` died with "export 'createFox' must return a
|
|
121
|
+
* THREE.Object3D, got object", closing the fast look door to every
|
|
122
|
+
* parametric lib including the kit's own worked examples.
|
|
123
|
+
*
|
|
124
|
+
* ANIMATIONS RIDE ON `root.animations`, always. That is three's own carrier —
|
|
125
|
+
* where `GLTFLoader` puts clips, what `Object3D.copy` carries across a clone,
|
|
126
|
+
* what `useAnimations(scene.animations)` reads — so a build result's separate
|
|
127
|
+
* `animations` list is written onto the root here and every downstream reader
|
|
128
|
+
* (the GLB writer, the preview exporter, the Asset Lab's transport) keeps
|
|
129
|
+
* working unchanged. A root that already carries clips is left alone.
|
|
130
|
+
*/
|
|
131
|
+
export interface ModuleBuild {
|
|
132
|
+
readonly root: THREE.Object3D;
|
|
133
|
+
/** The builder's OWN teardown, when it returned one. The caller runs it
|
|
134
|
+
* instead of a generic graph dispose: a rig holds mixers, actions and
|
|
135
|
+
* materials a `traverse` walk does not know about. */
|
|
136
|
+
readonly dispose?: () => void;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Normalize any accepted shape, or `undefined` when it is none of them. */
|
|
140
|
+
function asModuleBuild(built: unknown): ModuleBuild | undefined {
|
|
141
|
+
if (!built || typeof built !== 'object') return undefined;
|
|
142
|
+
if ((built as THREE.Object3D).isObject3D === true) return { root: built as THREE.Object3D };
|
|
143
|
+
// 3. A MODEL MODULE — `build(): THREE.BufferGeometry` (`lib/mesh/geometry`).
|
|
144
|
+
// Geometry has no material; the lane photographs and bakes it under a
|
|
145
|
+
// neutral standard material, named for the export.
|
|
146
|
+
if ((built as THREE.BufferGeometry).isBufferGeometry === true) {
|
|
147
|
+
return {
|
|
148
|
+
root: new THREE.Mesh(built as THREE.BufferGeometry, new THREE.MeshStandardMaterial()),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const result = built as { root?: unknown; animations?: unknown; dispose?: unknown };
|
|
152
|
+
const root = result.root as THREE.Object3D | undefined;
|
|
153
|
+
if (!root || typeof root !== 'object' || root.isObject3D !== true) return undefined;
|
|
154
|
+
if (Array.isArray(result.animations) && root.animations.length === 0) {
|
|
155
|
+
root.animations = result.animations as THREE.AnimationClip[];
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
root,
|
|
159
|
+
...(typeof result.dispose === 'function'
|
|
160
|
+
? { dispose: () => (result.dispose as () => void).call(built) }
|
|
161
|
+
: {}),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Import the project module and call its named export, matching the turntable `?module=&export=` contract.
|
|
167
|
+
*
|
|
168
|
+
* `loadModule` is the HOST's loader (`ctx.loadProjectModule`: the editor
|
|
169
|
+
* server's Vite SSR loader, which re-transforms a module — and everything it
|
|
170
|
+
* imports — when any file in that graph changes). Prefer it whenever the
|
|
171
|
+
* caller has one. The raw `import()` fallback is for a tool running outside an
|
|
172
|
+
* editor server, and it is a ONE-SHOT door: Node's ESM cache keys on the URL
|
|
173
|
+
* and never invalidates, so inside a long-lived server it returned the first
|
|
174
|
+
* version of `src/models/barrel.ts` for every later look until the server was
|
|
175
|
+
* restarted (the blind modeling bench measured three `vgai restart`s in one
|
|
176
|
+
* barrel, 2026-09-05).
|
|
177
|
+
*/
|
|
178
|
+
export async function buildFromModule(
|
|
179
|
+
projectRoot: string,
|
|
180
|
+
modulePath: string,
|
|
181
|
+
exportName: string,
|
|
182
|
+
loadModule?: (absolutePath: string) => Promise<unknown>,
|
|
183
|
+
): Promise<ModuleBuild> {
|
|
184
|
+
const absolute = await resolveProjectModule(projectRoot, modulePath);
|
|
185
|
+
let mod: Record<string, unknown>;
|
|
186
|
+
try {
|
|
187
|
+
mod = (
|
|
188
|
+
loadModule
|
|
189
|
+
? await loadModule(absolute)
|
|
190
|
+
: await import(/* @vite-ignore */ pathToFileURL(absolute).href)
|
|
191
|
+
) as Record<string, unknown>;
|
|
192
|
+
} catch (error) {
|
|
193
|
+
throw new ToolError(
|
|
194
|
+
MODULE_NOT_FOUND_ERROR.code,
|
|
195
|
+
`module '${modulePath}' failed to import: ${error instanceof Error ? error.message : String(error)}`,
|
|
196
|
+
{ modulePath, reason: error instanceof Error ? error.message : String(error) },
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
// A MODEL MODULE's builder is `build` (`lib/mesh/geometry`'s contract), so a
|
|
200
|
+
// caller asking for the default export of a module that has none but has
|
|
201
|
+
// `build` gets the model — `vgai screenshot src/models/cube.ts` needs no flag.
|
|
202
|
+
const exp = mod[exportName] ?? (exportName === 'default' ? mod['build'] : undefined);
|
|
203
|
+
if (exp === undefined) {
|
|
204
|
+
throw new ToolError(
|
|
205
|
+
EXPORT_NOT_CALLABLE_ERROR.code,
|
|
206
|
+
`module '${modulePath}' has no export '${exportName}' (exports: ${Object.keys(mod).join(', ')})`,
|
|
207
|
+
{ modulePath, exportName, available: Object.keys(mod) },
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
if (typeof exp !== 'function') {
|
|
211
|
+
throw new ToolError(
|
|
212
|
+
EXPORT_NOT_CALLABLE_ERROR.code,
|
|
213
|
+
`module '${modulePath}' export '${exportName}' must be a function returning a THREE.Object3D or THREE.BufferGeometry.`,
|
|
214
|
+
{ modulePath, exportName, available: Object.keys(mod) },
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
const built = (await exp()) as unknown;
|
|
218
|
+
const build = asModuleBuild(built);
|
|
219
|
+
if (!build) {
|
|
220
|
+
throw new ToolError(
|
|
221
|
+
NOT_AN_OBJECT3D_ERROR.code,
|
|
222
|
+
`module '${modulePath}' export '${exportName}' must return a THREE.BufferGeometry (a model ` +
|
|
223
|
+
'module), a THREE.Object3D, or a build result `{ root, animations?, dispose? }` whose ' +
|
|
224
|
+
"`root` is one (the kit's parametric libs — createBird, createHumanoid — return that " +
|
|
225
|
+
`shape). Got ${describeReturn(built)}.`,
|
|
226
|
+
{ modulePath, exportName, returnedType: typeof built },
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
return build;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** What the export actually returned, for the refusal above — `object` alone
|
|
233
|
+
* cannot tell a build result with a mistyped key from an unrelated value. */
|
|
234
|
+
function describeReturn(built: unknown): string {
|
|
235
|
+
if (built === null) return 'null';
|
|
236
|
+
if (typeof built !== 'object') return typeof built;
|
|
237
|
+
if (Array.isArray(built)) return 'an array';
|
|
238
|
+
const keys = Object.keys(built);
|
|
239
|
+
return keys.length > 0
|
|
240
|
+
? `an object with keys ${keys.slice(0, 8).join(', ')}`
|
|
241
|
+
: 'an object with no own keys';
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function computeMeshStats(root: THREE.Object3D): {
|
|
245
|
+
vertexCount: number;
|
|
246
|
+
triangleCount: number;
|
|
247
|
+
/** See {@link countInvertedTriangles}. */
|
|
248
|
+
invertedTriangleCount: number;
|
|
249
|
+
/** Edges with exactly one triangle on them after welding by position —
|
|
250
|
+
* a hole, an unclosed cap, or a part that was never joined. See
|
|
251
|
+
* {@link countInvertedTriangles}, which measures both in one pass. */
|
|
252
|
+
boundaryEdgeCount: number;
|
|
253
|
+
/** World-space midpoints of up to six of those edges. */
|
|
254
|
+
boundaryEdgeSamples: [number, number, number][];
|
|
255
|
+
/** Vertices whose position is NaN or infinite. Three.js reports these as
|
|
256
|
+
* "computeBoundingBox(): Computed min/max have NaN values" on the console,
|
|
257
|
+
* naming no op and no line — a blind session spent five minutes with its
|
|
258
|
+
* own probe script finding where (2026-09-06). The look names the count. */
|
|
259
|
+
nonFiniteVertexCount: number;
|
|
260
|
+
} {
|
|
261
|
+
let vertexCount = 0;
|
|
262
|
+
let triangleCount = 0;
|
|
263
|
+
let invertedTriangleCount = 0;
|
|
264
|
+
let boundaryEdgeCount = 0;
|
|
265
|
+
let nonFiniteVertexCount = 0;
|
|
266
|
+
const boundaryEdgeSamples: [number, number, number][] = [];
|
|
267
|
+
root.traverse((object) => {
|
|
268
|
+
const mesh = object as THREE.Mesh;
|
|
269
|
+
if (!mesh.isMesh) return;
|
|
270
|
+
const position = mesh.geometry.getAttribute('position');
|
|
271
|
+
const index = mesh.geometry.getIndex();
|
|
272
|
+
vertexCount += position?.count ?? 0;
|
|
273
|
+
if (position) {
|
|
274
|
+
for (let i = 0; i < position.count; i += 1) {
|
|
275
|
+
if (
|
|
276
|
+
!Number.isFinite(position.getX(i)) ||
|
|
277
|
+
!Number.isFinite(position.getY(i)) ||
|
|
278
|
+
!Number.isFinite(position.getZ(i))
|
|
279
|
+
) {
|
|
280
|
+
nonFiniteVertexCount += 1;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
triangleCount += index ? index.count / 3 : (position?.count ?? 0) / 3;
|
|
285
|
+
const winding = countInvertedTriangles(mesh.geometry);
|
|
286
|
+
invertedTriangleCount += winding.inverted;
|
|
287
|
+
boundaryEdgeCount += winding.boundaryEdges;
|
|
288
|
+
// World space, as the brief's numbers are: the mesh's own transform applied.
|
|
289
|
+
mesh.updateWorldMatrix(true, false);
|
|
290
|
+
for (const [x, y, z] of winding.boundaryEdgeSamples) {
|
|
291
|
+
if (boundaryEdgeSamples.length >= 6) break;
|
|
292
|
+
const p = new THREE.Vector3(x, y, z).applyMatrix4(mesh.matrixWorld);
|
|
293
|
+
boundaryEdgeSamples.push([p.x, p.y, p.z]);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
return {
|
|
297
|
+
vertexCount,
|
|
298
|
+
triangleCount,
|
|
299
|
+
invertedTriangleCount,
|
|
300
|
+
boundaryEdgeCount,
|
|
301
|
+
boundaryEdgeSamples,
|
|
302
|
+
nonFiniteVertexCount,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Triangles that FACE INWARD — the two ways a mesh gets there, counted the way
|
|
308
|
+
* Blender's Face Orientation overlay would paint them red:
|
|
309
|
+
*
|
|
310
|
+
* 1. an inside-out CLOSED SHELL (every edge shared by exactly two triangles)
|
|
311
|
+
* — its signed volume is negative, so every triangle in it is inverted.
|
|
312
|
+
* A shell that is consistently wound the wrong way has no local tell at
|
|
313
|
+
* all: every neighbour agrees with it, and only its volume says which side
|
|
314
|
+
* is out (`bmesh.ops.recalc_face_normals` decides the same way);
|
|
315
|
+
* 2. NON-CONTIGUOUS pairs — two triangles traversing a shared edge in the
|
|
316
|
+
* same direction, so their normals disagree (what the kit's `validate()`
|
|
317
|
+
* reports as `inconsistentWinding`). Both are counted; the count is a
|
|
318
|
+
* "how much is wrong" number, not a repair plan.
|
|
319
|
+
*
|
|
320
|
+
* Why the look verb needs this: the editor's model stage lights both sides,
|
|
321
|
+
* so a shell that is 60 % inverted photographs as a clean solid — the blind
|
|
322
|
+
* modeling bench shipped exactly that (a barrel whose 12 staves were built
|
|
323
|
+
* inside out, 432 of 720 triangles, reported "all features verified") while
|
|
324
|
+
* Blender rendered the same GLB dark. A picture that cannot show the defect
|
|
325
|
+
* has to SAY it.
|
|
326
|
+
*
|
|
327
|
+
* Vertices are welded by position (1e-5) first, so the flat-shaded, per-face
|
|
328
|
+
* vertex layout the mesh kit exports still resolves to shared edges.
|
|
329
|
+
*/
|
|
330
|
+
export function countInvertedTriangles(geometry: THREE.BufferGeometry): {
|
|
331
|
+
inverted: number;
|
|
332
|
+
boundaryEdges: number;
|
|
333
|
+
/** Midpoints of the first few open edges, so a count becomes a place —
|
|
334
|
+
* four blind sessions accepted "2 open edges" because nothing said where. */
|
|
335
|
+
boundaryEdgeSamples: [number, number, number][];
|
|
336
|
+
} {
|
|
337
|
+
const position = geometry.getAttribute('position');
|
|
338
|
+
if (!position) return { inverted: 0, boundaryEdges: 0, boundaryEdgeSamples: [] };
|
|
339
|
+
const index = geometry.getIndex();
|
|
340
|
+
const triCount = index ? Math.floor(index.count / 3) : Math.floor(position.count / 3);
|
|
341
|
+
if (triCount === 0) return { inverted: 0, boundaryEdges: 0, boundaryEdgeSamples: [] };
|
|
342
|
+
const keyOf = new Map<string, number>();
|
|
343
|
+
const welded = new Int32Array(position.count);
|
|
344
|
+
for (let i = 0; i < position.count; i += 1) {
|
|
345
|
+
// Integer keys: `(-0).toFixed(5)` is "-0.00000" and never welds with
|
|
346
|
+
// "0.00000", which split every seam that landed on an axis and reported
|
|
347
|
+
// it as open edges (a barrel's head cylinders, blind bench 2026-09-06).
|
|
348
|
+
const key = `${Math.round(position.getX(i) * 1e5) || 0},${Math.round(position.getY(i) * 1e5) || 0},${Math.round(position.getZ(i) * 1e5) || 0}`;
|
|
349
|
+
let id = keyOf.get(key);
|
|
350
|
+
if (id === undefined) {
|
|
351
|
+
id = keyOf.size;
|
|
352
|
+
keyOf.set(key, id);
|
|
353
|
+
}
|
|
354
|
+
welded[i] = id;
|
|
355
|
+
}
|
|
356
|
+
const corner = (tri: number, k: number): number => {
|
|
357
|
+
const raw = index ? index.getX(tri * 3 + k) : tri * 3 + k;
|
|
358
|
+
return welded[raw] ?? 0;
|
|
359
|
+
};
|
|
360
|
+
// Union-find over welded vertices → connected shells.
|
|
361
|
+
const parent = new Int32Array(keyOf.size);
|
|
362
|
+
for (let i = 0; i < parent.length; i += 1) parent[i] = i;
|
|
363
|
+
const find = (a: number): number => {
|
|
364
|
+
let r = a;
|
|
365
|
+
while (parent[r] !== r) r = parent[r] as number;
|
|
366
|
+
while (parent[a] !== r) {
|
|
367
|
+
const next = parent[a] as number;
|
|
368
|
+
parent[a] = r;
|
|
369
|
+
a = next;
|
|
370
|
+
}
|
|
371
|
+
return r;
|
|
372
|
+
};
|
|
373
|
+
const union = (a: number, b: number) => {
|
|
374
|
+
const ra = find(a);
|
|
375
|
+
const rb = find(b);
|
|
376
|
+
if (ra !== rb) parent[ra] = rb;
|
|
377
|
+
};
|
|
378
|
+
const directed = new Map<string, number>();
|
|
379
|
+
const undirected = new Map<string, number>();
|
|
380
|
+
const tris: Array<[number, number, number]> = [];
|
|
381
|
+
for (let t = 0; t < triCount; t += 1) {
|
|
382
|
+
const a = corner(t, 0);
|
|
383
|
+
const b = corner(t, 1);
|
|
384
|
+
const c = corner(t, 2);
|
|
385
|
+
if (a === b || b === c || c === a) continue; // degenerate: no edge to disagree over
|
|
386
|
+
tris.push([a, b, c]);
|
|
387
|
+
union(a, b);
|
|
388
|
+
union(b, c);
|
|
389
|
+
for (const [u, v] of [
|
|
390
|
+
[a, b],
|
|
391
|
+
[b, c],
|
|
392
|
+
[c, a],
|
|
393
|
+
] as const) {
|
|
394
|
+
const d = `${u}>${v}`;
|
|
395
|
+
directed.set(d, (directed.get(d) ?? 0) + 1);
|
|
396
|
+
const un = u < v ? `${u}-${v}` : `${v}-${u}`;
|
|
397
|
+
undirected.set(un, (undirected.get(un) ?? 0) + 1);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
// Per shell: closed? signed volume.
|
|
401
|
+
const closed = new Map<number, boolean>();
|
|
402
|
+
const volume = new Map<number, number>();
|
|
403
|
+
for (const [a, b, c] of tris) {
|
|
404
|
+
const shell = find(a);
|
|
405
|
+
if (!closed.has(shell)) closed.set(shell, true);
|
|
406
|
+
for (const [u, v] of [
|
|
407
|
+
[a, b],
|
|
408
|
+
[b, c],
|
|
409
|
+
[c, a],
|
|
410
|
+
] as const) {
|
|
411
|
+
const un = u < v ? `${u}-${v}` : `${v}-${u}`;
|
|
412
|
+
if (undirected.get(un) !== 2) closed.set(shell, false);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
// Signed volume needs coordinates: read one representative position per welded id.
|
|
416
|
+
const rep = new Float64Array(keyOf.size * 3);
|
|
417
|
+
const seen = new Uint8Array(keyOf.size);
|
|
418
|
+
for (let i = 0; i < position.count; i += 1) {
|
|
419
|
+
const id = welded[i] as number;
|
|
420
|
+
if (seen[id]) continue;
|
|
421
|
+
seen[id] = 1;
|
|
422
|
+
rep[id * 3] = position.getX(i);
|
|
423
|
+
rep[id * 3 + 1] = position.getY(i);
|
|
424
|
+
rep[id * 3 + 2] = position.getZ(i);
|
|
425
|
+
}
|
|
426
|
+
for (const [a, b, c] of tris) {
|
|
427
|
+
const shell = find(a);
|
|
428
|
+
const ax = rep[a * 3] as number;
|
|
429
|
+
const ay = rep[a * 3 + 1] as number;
|
|
430
|
+
const az = rep[a * 3 + 2] as number;
|
|
431
|
+
const bx = rep[b * 3] as number;
|
|
432
|
+
const by = rep[b * 3 + 1] as number;
|
|
433
|
+
const bz = rep[b * 3 + 2] as number;
|
|
434
|
+
const cx = rep[c * 3] as number;
|
|
435
|
+
const cy = rep[c * 3 + 1] as number;
|
|
436
|
+
const cz = rep[c * 3 + 2] as number;
|
|
437
|
+
// a · (b × c) / 6
|
|
438
|
+
const v = (ax * (by * cz - bz * cy) - ay * (bx * cz - bz * cx) + az * (bx * cy - by * cx)) / 6;
|
|
439
|
+
volume.set(shell, (volume.get(shell) ?? 0) + v);
|
|
440
|
+
}
|
|
441
|
+
let boundaryEdges = 0;
|
|
442
|
+
const boundaryEdgeSamples: [number, number, number][] = [];
|
|
443
|
+
for (const [edge, count] of undirected) {
|
|
444
|
+
if (count !== 1) continue;
|
|
445
|
+
boundaryEdges += 1;
|
|
446
|
+
if (boundaryEdgeSamples.length >= 6) continue;
|
|
447
|
+
const [u, v] = edge.split('-').map(Number) as [number, number];
|
|
448
|
+
boundaryEdgeSamples.push([
|
|
449
|
+
((rep[u * 3] as number) + (rep[v * 3] as number)) / 2,
|
|
450
|
+
((rep[u * 3 + 1] as number) + (rep[v * 3 + 1] as number)) / 2,
|
|
451
|
+
((rep[u * 3 + 2] as number) + (rep[v * 3 + 2] as number)) / 2,
|
|
452
|
+
]);
|
|
453
|
+
}
|
|
454
|
+
let inverted = 0;
|
|
455
|
+
for (const [a, b, c] of tris) {
|
|
456
|
+
const shell = find(a);
|
|
457
|
+
if (closed.get(shell) && (volume.get(shell) ?? 0) < 0) {
|
|
458
|
+
inverted += 1;
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
// Non-contiguous only means something on a MANIFOLD edge (exactly two
|
|
462
|
+
// triangles). Two separate closed solids that touch along a knife edge
|
|
463
|
+
// — a barrel's staves at the groove apex, a lantern's collar on its roof
|
|
464
|
+
// — share that edge four ways after welding, every direction twice, and
|
|
465
|
+
// both solids are wound perfectly well. Two blind-bench sessions each
|
|
466
|
+
// spent several looks chasing that report before this line existed.
|
|
467
|
+
const manifold = (u: number, v: number) =>
|
|
468
|
+
undirected.get(u < v ? `${u}-${v}` : `${v}-${u}`) === 2;
|
|
469
|
+
if (
|
|
470
|
+
(manifold(a, b) && (directed.get(`${a}>${b}`) ?? 0) > 1) ||
|
|
471
|
+
(manifold(b, c) && (directed.get(`${b}>${c}`) ?? 0) > 1) ||
|
|
472
|
+
(manifold(c, a) && (directed.get(`${c}>${a}`) ?? 0) > 1)
|
|
473
|
+
) {
|
|
474
|
+
inverted += 1;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return { inverted, boundaryEdges, boundaryEdgeSamples };
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/** Every mesh in the built graph, for the mesh-count facts both verbs report. */
|
|
481
|
+
export function countMeshes(root: THREE.Object3D): number {
|
|
482
|
+
let meshCount = 0;
|
|
483
|
+
root.traverse((object) => {
|
|
484
|
+
if ((object as THREE.Mesh).isMesh) meshCount += 1;
|
|
485
|
+
});
|
|
486
|
+
return meshCount;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/** The shared "did the builder produce anything renderable?" gate. */
|
|
490
|
+
export function assertRenderableGeometry(
|
|
491
|
+
stats: { vertexCount: number; triangleCount: number },
|
|
492
|
+
modulePath: string,
|
|
493
|
+
exportName: string,
|
|
494
|
+
): void {
|
|
495
|
+
if (stats.vertexCount > 0 && stats.triangleCount > 0) return;
|
|
496
|
+
throw new ToolError(
|
|
497
|
+
EMPTY_GEOMETRY_ERROR.code,
|
|
498
|
+
`module '${modulePath}' export '${exportName}' produced an Object3D with no ` +
|
|
499
|
+
'renderable geometry.',
|
|
500
|
+
{ modulePath, exportName },
|
|
501
|
+
);
|
|
502
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `pagesFromUiModules` FINDER (ARCHITECTURE-CORE §The project model,
|
|
3
|
+
* "Documents, not scenes"): every project module under the selection's
|
|
4
|
+
* `include` globs that exports a React component is a `page` document —
|
|
5
|
+
* what a website is made of, the way a game is made of scenes. Select it
|
|
6
|
+
* in `vgai.adapter.ts`:
|
|
7
|
+
*
|
|
8
|
+
* documents: { find: [{ finder: 'pagesFromUiModules', include: ['src/ui/**\/*page.tsx'] }] }
|
|
9
|
+
*
|
|
10
|
+
* The glob IS the page rule: a project names its pages by where it keeps
|
|
11
|
+
* them. This module is a plain object the HOST registers; it mounts no UI
|
|
12
|
+
* and reads the project only through `input.sources`.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
|
|
16
|
+
const COMPONENT_EXPORT =
|
|
17
|
+
/export\s+(?:default\s+)?(?:function\s+[A-Z]\w*\s*\(|const\s+[A-Z]\w*\s*[:=])/;
|
|
18
|
+
|
|
19
|
+
export const finder = {
|
|
20
|
+
name: 'pagesFromUiModules',
|
|
21
|
+
schema: z
|
|
22
|
+
.object({
|
|
23
|
+
finder: z.literal('pagesFromUiModules'),
|
|
24
|
+
include: z
|
|
25
|
+
.array(z.string().min(1))
|
|
26
|
+
.min(1)
|
|
27
|
+
.describe('Project-relative globs of the page modules (`src/ui/**/*page.tsx`)'),
|
|
28
|
+
})
|
|
29
|
+
.strict(),
|
|
30
|
+
run(
|
|
31
|
+
_selection: { finder: 'pagesFromUiModules'; include: readonly string[] },
|
|
32
|
+
input: { sources?: readonly { path: string; source: string }[] },
|
|
33
|
+
) {
|
|
34
|
+
const entries = [];
|
|
35
|
+
const notes: string[] = [];
|
|
36
|
+
for (const file of input.sources ?? []) {
|
|
37
|
+
if (!COMPONENT_EXPORT.test(file.source)) {
|
|
38
|
+
notes.push(`${file.path}: exports no component — not a page`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const name = (file.path.split('/').pop() ?? file.path)
|
|
42
|
+
.replace(/\.[cm]?[jt]sx?$/, '')
|
|
43
|
+
.replace(/[-_.]?page$/i, '');
|
|
44
|
+
entries.push({
|
|
45
|
+
id: `page:${file.path}`,
|
|
46
|
+
label: name || 'page',
|
|
47
|
+
kind: 'page',
|
|
48
|
+
region: null,
|
|
49
|
+
authorable: true,
|
|
50
|
+
reach: { kind: 'root-mount' as const },
|
|
51
|
+
source: { path: file.path },
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
entries,
|
|
56
|
+
notes,
|
|
57
|
+
// One page is the page; two is a choice the site's author states.
|
|
58
|
+
...(entries.length === 1 ? { default: entries[0]!.id } : {}),
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
} as const;
|