incanto 0.66.0 → 0.67.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/_behaviors-loader.mjs +87 -0
- package/bin/incanto-editor.mjs +39 -2
- package/bin/incanto-feel.mjs +4 -1
- package/bin/incanto-frame.mjs +52 -3
- package/bin/incanto-logs.mjs +33 -3
- package/bin/incanto-multiplay.mjs +50 -1
- package/bin/incanto-play.mjs +3 -1
- package/bin/incanto-playtest.mjs +3 -25
- package/bin/incanto-verify.mjs +15 -2
- package/dist/2d.d.ts +41 -4
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +86 -14
- package/dist/3d.js +6 -6
- package/dist/{audio-player-_UAcHxnC.d.ts → audio-player-BNUHo0JF.d.ts} +1 -1
- package/dist/{behavior-BXNLfIJk.d.ts → behavior-ZnfzKDo3.d.ts} +39 -1
- package/dist/{create-game-Dd7H4bJV.js → create-game-DMetd3vR.js} +14 -8
- package/dist/{create-game-DYJCIzO0.js → create-game-FAXdHta3.js} +77 -11
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +3 -2
- package/dist/{duplicate-CqSAtdrh.js → duplicate-B8QnX2-r.js} +1 -1
- package/dist/editor.js +7 -2
- package/dist/{environment-presets-BlPsEmq6.js → environment-presets-C-5g2pMh.js} +46 -6
- package/dist/{gameplay-D1RADWu3.js → gameplay-CGSv-9XR.js} +28 -5
- package/dist/gameplay.d.ts +25 -4
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +50 -6
- package/dist/index.js +7 -6
- package/dist/{loader-Cga7FVP4.d.ts → loader-DyT30ArB.d.ts} +1 -1
- package/dist/{loader-lQDCwNag.js → loader-KZESOZmE.js} +148 -1
- package/dist/net.d.ts +2 -2
- package/dist/net.js +1 -1
- package/dist/{physics-2d-Cji5A6sX.js → physics-2d-_B6zj3zU.js} +29 -2
- package/dist/{physics-3d-BkHjwJgI.js → physics-3d-i1IeAY0F.js} +30 -3
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-BmuqYTiY.js → register-Cs53CY7s.js} +81 -16
- package/dist/{register-D0CxCveZ.js → register-vIxU3Xbv.js} +3 -3
- package/dist/rendering-options-ByAdi8PF.js +184 -0
- package/dist/{replay-IsZbNu6d.js → replay-BkpDV51O.js} +4 -3
- package/dist/{replay-BHoB6fCU.d.ts → replay-D0GcEHYU.d.ts} +1 -1
- package/dist/{split-screen-eJUFjhi1.d.ts → split-screen-DD5eYIgW.d.ts} +2 -2
- package/dist/{split-screen-D_i7GRcY.js → split-screen-DS8RaUV_.js} +2 -2
- package/dist/{src-BTLbXFPZ.js → src-BLlsGJW9.js} +1 -1
- package/dist/{teardown-byR9USax.js → teardown-LB9cTnXJ.js} +2 -2
- package/dist/{test-DgrD0jHD.js → test-81uZ967a.js} +127 -24
- package/dist/test.d.ts +7 -5
- package/dist/test.js +2 -2
- package/dist/{touch-DESwnpOc.js → touch-DEAmqGdf.js} +30 -186
- package/dist/vite.d.ts +0 -7
- package/dist/vite.js +13 -3
- package/editor/assets/{agent8-9N-Pd_YS.js → agent8-C2jtNKbx.js} +1 -1
- package/editor/assets/debug-DoU3KeqS.js +3 -0
- package/editor/assets/{index-CeDhIPTC.js → index-CNqHojcC.js} +92 -92
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +1 -1
- package/skills/incanto-building-3d-games.md +19 -0
- package/skills/incanto-editor.md +5 -1
- package/skills/incanto-environment.md +2 -2
- package/skills/incanto-gameplay-behaviors.md +1 -1
- package/skills/incanto-hud.md +14 -1
- package/skills/incanto-multiplayer.md +14 -0
- package/skills/incanto-node-reference.md +1 -1
- package/skills/incanto-performance.md +35 -0
- package/skills/incanto-playtesting.md +15 -1
- package/skills/incanto-save-slots.md +21 -1
- package/skills/incanto-verifying-your-game.md +19 -0
- package/skills/incanto-your-first-game.md +4 -4
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/beacon-isle-3d/src/game.scene.json +38 -19
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/platformer-2d/src/game.scene.json +99 -53
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/star-survivor/src/game.scene.json +31 -17
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/tps-3d/src/game.scene.json +14 -8
- package/templates-app/village-quest-3d/package.json +1 -1
- package/templates-app/village-quest-3d/src/grove.scene.json +20 -11
- package/templates-app/village-quest-3d/src/village.scene.json +10 -7
- package/editor/assets/debug-CkbJICYp.js +0 -3
package/dist/3d.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { D as QualityCaps, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats } from "./behavior-
|
|
1
|
+
import { D as QualityCaps, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats, x as EngineOptions } from "./behavior-ZnfzKDo3.js";
|
|
2
2
|
import { n as DiagnosticSink, t as EditorSwitchOptions } from "./editor-switch-DAvWQeld.js";
|
|
3
3
|
import { i as SceneJson$1, s as JsonObject } from "./schema-CFeioQRE.js";
|
|
4
4
|
import { a as GridCell, c as diffText, d as frameText, i as FrameStatsOptions, l as frameSignature, n as FrameSignature, o as SIGNATURE_GRID, r as FrameStats, s as diffSignatures, t as FrameDiff, u as frameStats } from "./frame-report-DCnHFmto.js";
|
|
5
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
6
|
-
import { i as ParticleSim, o as ParticleView, r as SpatialPose } from "./audio-player-
|
|
5
|
+
import { t as LoadSceneOptions } from "./loader-DyT30ArB.js";
|
|
6
|
+
import { i as ParticleSim, o as ParticleView, r as SpatialPose } from "./audio-player-BNUHo0JF.js";
|
|
7
7
|
import { n as PathGrid } from "./pathfinding-_fGrCFmH.js";
|
|
8
8
|
import { AnimationClip, AnimationMixer, BufferGeometry, Color, DirectionalLight, Group, InstancedMesh, Mesh, MeshPhysicalMaterial, Object3D, PerspectiveCamera, Scene, ShaderMaterial, Texture, Vector3, WebGLRenderer } from "three";
|
|
9
9
|
import { VRM } from "@pixiv/three-vrm";
|
|
@@ -133,6 +133,31 @@ interface AnimationEntry {
|
|
|
133
133
|
*/
|
|
134
134
|
declare class AssetStore3D {
|
|
135
135
|
private readonly engine;
|
|
136
|
+
/**
|
|
137
|
+
* One geometry and one material per distinct SHAPE and per distinct look.
|
|
138
|
+
*
|
|
139
|
+
* `MeshInstance3D._createObject3D` used to `new BoxGeometry()` and
|
|
140
|
+
* `new MeshPhysicalMaterial()` for every node, even when byte-identical.
|
|
141
|
+
* Three identical nodes reported `geometry shared? false false / material
|
|
142
|
+
* shared? false false`, with distinct uuids. Measured at 3,200 units, all
|
|
143
|
+
* three runs at identical 3,209 draw calls / 1,741,932 triangles and an
|
|
144
|
+
* identical screenshot:
|
|
145
|
+
*
|
|
146
|
+
* ```
|
|
147
|
+
* per-node geometry + material 31.0 ms wall (renderMs 27.3)
|
|
148
|
+
* share one geometry 27.0 ms
|
|
149
|
+
* + share two materials 15.4 ms <- 2x the headroom
|
|
150
|
+
* ```
|
|
151
|
+
*
|
|
152
|
+
* 13.1 ms of that 26.5 ms cliff was GPU state churn from per-node objects,
|
|
153
|
+
* and none of it was visible headlessly: with no renderer `_syncObject3D`
|
|
154
|
+
* never runs, so the bench measured 55 ns/node instead of ~2,000.
|
|
155
|
+
*
|
|
156
|
+
* Renderer-scoped, deliberately — module-level state is the predecessor's
|
|
157
|
+
* fatal flaw and two games in one page must not share a cache.
|
|
158
|
+
*/
|
|
159
|
+
readonly meshGeometries: Map<string, unknown>;
|
|
160
|
+
readonly meshMaterials: Map<string, unknown>;
|
|
136
161
|
private readonly models;
|
|
137
162
|
private readonly animations;
|
|
138
163
|
private readonly modelKeys;
|
|
@@ -578,6 +603,16 @@ declare class Physics3D {
|
|
|
578
603
|
private readonly overlaps;
|
|
579
604
|
private trackOverlap;
|
|
580
605
|
/**
|
|
606
|
+
* Forget every overlap whose node has left the tree.
|
|
607
|
+
*
|
|
608
|
+
* The lazy drop inside `overlapping()` only cleans the SETS of a key someone
|
|
609
|
+
* asks about, and only when they ask. This clears the KEYS, which is where the
|
|
610
|
+
* dead nodes were pinned.
|
|
611
|
+
*/
|
|
612
|
+
/** Drop one node from the overlap map, both as a key and as a member. */
|
|
613
|
+
private forgetOverlaps;
|
|
614
|
+
private pruneOverlaps;
|
|
615
|
+
/**
|
|
581
616
|
* The bodies currently overlapping `node` — the standing answer behind
|
|
582
617
|
* `triggerEnter`/`triggerExit`.
|
|
583
618
|
*
|
|
@@ -683,6 +718,18 @@ interface CreateGame3DOptions {
|
|
|
683
718
|
*/
|
|
684
719
|
editor?: boolean | EditorSwitchOptions;
|
|
685
720
|
seed?: number;
|
|
721
|
+
/**
|
|
722
|
+
* Namespace this game's persisted settings — volume, language, quality tier.
|
|
723
|
+
*
|
|
724
|
+
* They are keyed `incanto:<namespace>:<key>` in the browser's storage and
|
|
725
|
+
* defaulted to `settings` for everyone, so two Incanto games on one domain
|
|
726
|
+
* shared one options screen. Measured: game A's player sets `renderScale
|
|
727
|
+
* 0.25, muted, quality low`; game B, whose source never mentions settings,
|
|
728
|
+
* boots at a 480x232 drawing buffer and silent.
|
|
729
|
+
*
|
|
730
|
+
* `SaveSlots(namespace)` already takes one for exactly this reason.
|
|
731
|
+
*/
|
|
732
|
+
settings?: EngineOptions["settings"];
|
|
686
733
|
fixedHz?: number;
|
|
687
734
|
pixelRatio?: number;
|
|
688
735
|
/** Keep the frame rate by rendering fewer pixels while frames run slow
|
|
@@ -732,7 +779,22 @@ interface GameRenderer {
|
|
|
732
779
|
}
|
|
733
780
|
interface Game3D {
|
|
734
781
|
engine: Engine;
|
|
735
|
-
|
|
782
|
+
/**
|
|
783
|
+
* The LIVE scene — a getter over `engine.scene`, not a snapshot.
|
|
784
|
+
*
|
|
785
|
+
* This used to be the scene captured at boot. `Engine.setScene` calls
|
|
786
|
+
* `this._scene?.root.free()`, so after any swap the old handle was not merely
|
|
787
|
+
* stale, it was EMPTIED — and a single-scene game reaches that through
|
|
788
|
+
* `flow.restart()`, which `incanto-hud.md` wires to a Start button. Measured:
|
|
789
|
+
*
|
|
790
|
+
* before swap game.scene.root.children = 2 engine.scene = 2
|
|
791
|
+
* after swap game.scene.root.children = 0 engine.scene = 2
|
|
792
|
+
* game.scene.root.getNode('Flow') -> No node at 'Flow'. Children here: [].
|
|
793
|
+
*
|
|
794
|
+
* `game.engine.scene` always worked and three skills use it, so there were
|
|
795
|
+
* two handles with one name and no note saying which was which.
|
|
796
|
+
*/
|
|
797
|
+
get scene(): Scene$1;
|
|
736
798
|
/**
|
|
737
799
|
* The AUTHORED scene this game booted from — the JSON, not the live tree.
|
|
738
800
|
*
|
|
@@ -1028,19 +1090,25 @@ declare class Environment3D {
|
|
|
1028
1090
|
}
|
|
1029
1091
|
//#endregion
|
|
1030
1092
|
//#region src/3d/environment-runtime.d.ts
|
|
1093
|
+
declare function setEnvironment3D(engine: Engine, patch: JsonObject, opts?: {
|
|
1094
|
+
rebaseTierKeys?: boolean;
|
|
1095
|
+
}): void;
|
|
1031
1096
|
/**
|
|
1032
|
-
*
|
|
1033
|
-
* every frame (cheap when unchanged), so changing the LOOK at runtime is
|
|
1034
|
-
* just writing that object. This helper does it safely:
|
|
1097
|
+
* Apply a quality tier — the only caller that may RESET as well as patch.
|
|
1035
1098
|
*
|
|
1036
|
-
*
|
|
1037
|
-
*
|
|
1099
|
+
* A tier is re-applied every time the player moves the slider, so it cannot
|
|
1100
|
+
* compose with what the last one left behind: `low` strips the author's bloom,
|
|
1101
|
+
* and `high` then has nothing to put back. This re-derives the four tier-owned
|
|
1102
|
+
* stages from the scene FILE first, so every tier is reversible, and so a stage
|
|
1103
|
+
* the author never wrote can never appear — the contract `settings.ts` states
|
|
1104
|
+
* and `incanto-performance.md` promises: *the tier can only take things away.*
|
|
1038
1105
|
*
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
1041
|
-
*
|
|
1106
|
+
* Measured before this, on a scene with no `bloom` and no `post` in its JSON:
|
|
1107
|
+
* `high` and `medium` both rendered five GL passes at 3.3 ms where `low`
|
|
1108
|
+
* rendered one at 1.24 ms — 62% of the frame on a chain the game never asked
|
|
1109
|
+
* for, and `environment.bloom` read back `{strength: 0.8, threshold: 1}`.
|
|
1042
1110
|
*/
|
|
1043
|
-
declare function
|
|
1111
|
+
declare function applyQualityTier3D(engine: Engine, patch: JsonObject): void;
|
|
1044
1112
|
//#endregion
|
|
1045
1113
|
//#region src/3d/model-verdict.d.ts
|
|
1046
1114
|
/**
|
|
@@ -1792,6 +1860,10 @@ declare class MeshInstance3D extends Node3D {
|
|
|
1792
1860
|
/** Loader hook: malformed materials fail at LOAD time, not at render. */
|
|
1793
1861
|
static validateJson(node: Node): void;
|
|
1794
1862
|
private geometryKey;
|
|
1863
|
+
private materialKey;
|
|
1864
|
+
/** True while this node is using a cache entry it must not dispose. */
|
|
1865
|
+
private sharedGeometry;
|
|
1866
|
+
private sharedMaterial;
|
|
1795
1867
|
private textureKey;
|
|
1796
1868
|
private loadedTextures;
|
|
1797
1869
|
protected override _createObject3D(): Object3D;
|
|
@@ -4034,4 +4106,4 @@ declare function createNavDebugNode(nav: TerrainNav, opts?: {
|
|
|
4034
4106
|
name?: string;
|
|
4035
4107
|
}): InstancedMesh3D;
|
|
4036
4108
|
//#endregion
|
|
4037
|
-
export { Area3D, AssetStore3D, type BedSampler, Billboard3D, type BillboardGroupMode, BoneAttachment3D, BoneLookAt3D, Camera3D, CharacterBody3D, CharacterController3D, type CreateGame3DOptions, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, type DownhillTraceOptions, Environment3D, type Environment3DConfig, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, type FlowerVariety, Flowers3D, type FogEnvironment, Foliage3D, type FoliageKind, type FoliageStyle, type FrameDiff, type FrameSignature, type FrameStats, type FrameStatsOptions, type Game3D, type GridCell, type HeightSampler, type Heightmap, type HeightmapOptions, InstancedMesh3D, Joint3D, type JointType3D, LoftMesh3D, type LoftSection, MeshInstance3D, type MeshKind, type MeshMaterialProps, type ModelEntry, type ModelFacts, ModelInstance3D, type ModelVerdict, Node3D, OmniLight3D, Particles3D, Physics3D, type Physics3DOptions, PhysicsBody3D, QUARTER_PITCH, type RenderContext3D, type RenderHook3D, Renderer3D, type Renderer3DOptions, type Rig, type RigView, RigidBody3D, type Ripple, River3D, type RiverCarveOptions, type RiverCoverageGap, type RiverHit, type RiverRing, type RiverRingOptions, SIGNATURE_GRID, type SceneJson, type ShadowsEnvironment, type SkyEnvironment, StaticBody3D, type SunConsumer3D, type SyncOptions, type SyncResult, TERRAIN_THEMES, Terrain3D, type TerrainLayer, type TerrainNav, type TerrainNavOptions, type TerrainTheme, TextureCache3D, type TextureSpec, Trail3D, Tree3D, type TreeTier, type TreeType, VOXEL_PALETTE, type VoxelBlock, VoxelGrid3D, WATER_CUTOUT_MAX, WATER_MAX_RIPPLES, Water3D, WaterCutout3D, acquireOwnTexture, acquireTexture, buildHeightmap, buildRiverRings, buildTerrainNav, cameraRelative, createGame3D, createNavDebugNode, diffSignatures, diffText, enablePhysics3D, findRiverCoverageGaps, frameSignature, frameStats, frameText, horizonColorFromSky, keyboardIntensity, modelVerdict, movementState, parseEnvironment3D, projectToRiver, registerNodes3D, resolveFlowerDensity, rigPose, riverCarveChannels, riverStepFor, setEnvironment3D, smoothCourse, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers, traceDownhillPath, verdictText };
|
|
4109
|
+
export { Area3D, AssetStore3D, type BedSampler, Billboard3D, type BillboardGroupMode, BoneAttachment3D, BoneLookAt3D, Camera3D, CharacterBody3D, CharacterController3D, type CreateGame3DOptions, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, type DownhillTraceOptions, Environment3D, type Environment3DConfig, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, type FlowerVariety, Flowers3D, type FogEnvironment, Foliage3D, type FoliageKind, type FoliageStyle, type FrameDiff, type FrameSignature, type FrameStats, type FrameStatsOptions, type Game3D, type GridCell, type HeightSampler, type Heightmap, type HeightmapOptions, InstancedMesh3D, Joint3D, type JointType3D, LoftMesh3D, type LoftSection, MeshInstance3D, type MeshKind, type MeshMaterialProps, type ModelEntry, type ModelFacts, ModelInstance3D, type ModelVerdict, Node3D, OmniLight3D, Particles3D, Physics3D, type Physics3DOptions, PhysicsBody3D, QUARTER_PITCH, type RenderContext3D, type RenderHook3D, Renderer3D, type Renderer3DOptions, type Rig, type RigView, RigidBody3D, type Ripple, River3D, type RiverCarveOptions, type RiverCoverageGap, type RiverHit, type RiverRing, type RiverRingOptions, SIGNATURE_GRID, type SceneJson, type ShadowsEnvironment, type SkyEnvironment, StaticBody3D, type SunConsumer3D, type SyncOptions, type SyncResult, TERRAIN_THEMES, Terrain3D, type TerrainLayer, type TerrainNav, type TerrainNavOptions, type TerrainTheme, TextureCache3D, type TextureSpec, Trail3D, Tree3D, type TreeTier, type TreeType, VOXEL_PALETTE, type VoxelBlock, VoxelGrid3D, WATER_CUTOUT_MAX, WATER_MAX_RIPPLES, Water3D, WaterCutout3D, acquireOwnTexture, acquireTexture, applyQualityTier3D, buildHeightmap, buildRiverRings, buildTerrainNav, cameraRelative, createGame3D, createNavDebugNode, diffSignatures, diffText, enablePhysics3D, findRiverCoverageGaps, frameSignature, frameStats, frameText, horizonColorFromSky, keyboardIntensity, modelVerdict, movementState, parseEnvironment3D, projectToRiver, registerNodes3D, resolveFlowerDensity, rigPose, riverCarveChannels, riverStepFor, setEnvironment3D, smoothCourse, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers, traceDownhillPath, verdictText };
|
package/dist/3d.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { c as parseEnvironment3D, l as sunDirectionFromElevationAzimuth, s as horizonColorFromSky, u as sunDirectionFromSky } from "./loader-
|
|
1
|
+
import { c as parseEnvironment3D, l as sunDirectionFromElevationAzimuth, s as horizonColorFromSky, u as sunDirectionFromSky } from "./loader-KZESOZmE.js";
|
|
2
2
|
import { a as frameSignature, n as diffSignatures, o as frameStats, r as diffText, s as frameText, t as SIGNATURE_GRID } from "./frame-report-BSMny7oe.js";
|
|
3
|
-
import { G as StaticBody3D, H as CharacterBody3D, K as Node3D, L as Water3D, R as WATER_CUTOUT_MAX, U as PhysicsBody3D, V as Area3D, W as RigidBody3D, Y as WATER_MAX_RIPPLES, z as WaterCutout3D } from "./gameplay-
|
|
4
|
-
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-
|
|
5
|
-
import { a as Environment3D, i as syncTree, o as
|
|
3
|
+
import { G as StaticBody3D, H as CharacterBody3D, K as Node3D, L as Water3D, R as WATER_CUTOUT_MAX, U as PhysicsBody3D, V as Area3D, W as RigidBody3D, Y as WATER_MAX_RIPPLES, z as WaterCutout3D } from "./gameplay-CGSv-9XR.js";
|
|
4
|
+
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-C-5g2pMh.js";
|
|
5
|
+
import { a as Environment3D, c as AssetStore3D, i as syncTree, o as applyQualityTier3D, r as Renderer3D, s as setEnvironment3D, t as createGame3D } from "./create-game-FAXdHta3.js";
|
|
6
6
|
import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
|
|
7
|
-
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-
|
|
7
|
+
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-i1IeAY0F.js";
|
|
8
8
|
//#region src/3d/model-verdict.ts
|
|
9
9
|
/** Mixamo exports every bone as `mixamorigX`; the retargeter binds by that name. */
|
|
10
10
|
const MIXAMO = /^mixamorig[:_]?/i;
|
|
@@ -317,4 +317,4 @@ function createNavDebugNode(nav, opts) {
|
|
|
317
317
|
return node;
|
|
318
318
|
}
|
|
319
319
|
//#endregion
|
|
320
|
-
export { Area3D, AssetStore3D, Billboard3D, BoneAttachment3D, BoneLookAt3D, Camera3D, CharacterBody3D, CharacterController3D, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, Environment3D, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, Flowers3D, Foliage3D, InstancedMesh3D, Joint3D, LoftMesh3D, MeshInstance3D, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, PhysicsBody3D, QUARTER_PITCH, Renderer3D, RigidBody3D, River3D, SIGNATURE_GRID, StaticBody3D, TERRAIN_THEMES, Terrain3D, TextureCache3D, Trail3D, Tree3D, VOXEL_PALETTE, VoxelGrid3D, WATER_CUTOUT_MAX, WATER_MAX_RIPPLES, Water3D, WaterCutout3D, acquireOwnTexture, acquireTexture, buildHeightmap, buildRiverRings, buildTerrainNav, cameraRelative, createGame3D, createNavDebugNode, diffSignatures, diffText, enablePhysics3D, findRiverCoverageGaps, frameSignature, frameStats, frameText, horizonColorFromSky, keyboardIntensity, modelVerdict, movementState, parseEnvironment3D, projectToRiver, registerNodes3D, resolveFlowerDensity, rigPose, riverCarveChannels, riverStepFor, setEnvironment3D, smoothCourse, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers, traceDownhillPath, verdictText };
|
|
320
|
+
export { Area3D, AssetStore3D, Billboard3D, BoneAttachment3D, BoneLookAt3D, Camera3D, CharacterBody3D, CharacterController3D, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, Environment3D, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, Flowers3D, Foliage3D, InstancedMesh3D, Joint3D, LoftMesh3D, MeshInstance3D, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, PhysicsBody3D, QUARTER_PITCH, Renderer3D, RigidBody3D, River3D, SIGNATURE_GRID, StaticBody3D, TERRAIN_THEMES, Terrain3D, TextureCache3D, Trail3D, Tree3D, VOXEL_PALETTE, VoxelGrid3D, WATER_CUTOUT_MAX, WATER_MAX_RIPPLES, Water3D, WaterCutout3D, acquireOwnTexture, acquireTexture, applyQualityTier3D, buildHeightmap, buildRiverRings, buildTerrainNav, cameraRelative, createGame3D, createNavDebugNode, diffSignatures, diffText, enablePhysics3D, findRiverCoverageGaps, frameSignature, frameStats, frameText, horizonColorFromSky, keyboardIntensity, modelVerdict, movementState, parseEnvironment3D, projectToRiver, registerNodes3D, resolveFlowerDensity, rigPose, riverCarveChannels, riverStepFor, setEnvironment3D, smoothCourse, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers, traceDownhillPath, verdictText };
|
|
@@ -16,6 +16,15 @@ declare class Signal<Args extends unknown[] = unknown[]> {
|
|
|
16
16
|
}): () => void;
|
|
17
17
|
disconnect(fn: SignalListener<Args>): void;
|
|
18
18
|
disconnectAll(): void;
|
|
19
|
+
/**
|
|
20
|
+
* How many listeners are attached.
|
|
21
|
+
*
|
|
22
|
+
* A leak is a SLOPE, and a game had no way to see one: every check in this
|
|
23
|
+
* engine is a snapshot. A handler connected per frame and never disconnected,
|
|
24
|
+
* or a `once` that armed and never fired, accumulates invisibly and is
|
|
25
|
+
* perfectly healthy for the first thirty seconds of every playthrough.
|
|
26
|
+
*/
|
|
27
|
+
get count(): number;
|
|
19
28
|
emit(...args: Args): void;
|
|
20
29
|
get connectionCount(): number;
|
|
21
30
|
}
|
|
@@ -247,6 +256,14 @@ declare class Node implements NodeLifecycle {
|
|
|
247
256
|
once?: boolean;
|
|
248
257
|
}): () => void;
|
|
249
258
|
off(signal: string, fn: SignalListener<unknown[]>): void;
|
|
259
|
+
/**
|
|
260
|
+
* How many listeners this node has on `signal` — 0 for one nobody watches.
|
|
261
|
+
*
|
|
262
|
+
* The engine's own leak test reads it, and so can a game: a handler connected
|
|
263
|
+
* every frame and never disconnected is invisible to every other check here,
|
|
264
|
+
* because every other check is a snapshot and a leak is a slope.
|
|
265
|
+
*/
|
|
266
|
+
listenerCount(signal: string): number;
|
|
250
267
|
emit(signal: string, ...args: unknown[]): void;
|
|
251
268
|
/**
|
|
252
269
|
* Defer destruction to the end of the current update pass (flushed by the
|
|
@@ -1220,7 +1237,8 @@ interface RestoreReport {
|
|
|
1220
1237
|
declare function captureBehaviors(root: Node, source?: JsonValue): {
|
|
1221
1238
|
state: BehaviorState; /** Paths of nodes that had state to save and no uid to save it under. */
|
|
1222
1239
|
unaddressable: string[]; /** Behaviors in this tree that have something to save — addressable or not. */
|
|
1223
|
-
saveable: number;
|
|
1240
|
+
saveable: number; /** Authored nodes this run consumed that the `#freed` ledger cannot record. */
|
|
1241
|
+
unrecordable: string[];
|
|
1224
1242
|
};
|
|
1225
1243
|
/**
|
|
1226
1244
|
* Hand each behavior its state back.
|
|
@@ -1600,6 +1618,26 @@ interface EngineOptions {
|
|
|
1600
1618
|
seed?: number;
|
|
1601
1619
|
/** Frame cap in fps; 0 (default) runs at whatever the display offers. */
|
|
1602
1620
|
maxFps?: number;
|
|
1621
|
+
/**
|
|
1622
|
+
* Which SETTINGS this game owns — its own, or the origin's.
|
|
1623
|
+
*
|
|
1624
|
+
* Persisted settings are keyed `incanto:<namespace>:<key>` in the browser's
|
|
1625
|
+
* storage, and this defaulted to `settings` with no way to change it. So two
|
|
1626
|
+
* Incanto games served from one domain shared one volume slider, one language
|
|
1627
|
+
* and one quality tier. Measured: game A's player sets
|
|
1628
|
+
* `renderScale 0.25, muted, quality low`; game B — whose source never mentions
|
|
1629
|
+
* settings — boots at a 480×232 drawing buffer, silent.
|
|
1630
|
+
*
|
|
1631
|
+
* `SaveSlots(namespace)` and `createSaveStore(namespace)` have always taken
|
|
1632
|
+
* one and document it as "keeps two games on one origin apart". This is the
|
|
1633
|
+
* third sibling finally saying the same thing.
|
|
1634
|
+
*
|
|
1635
|
+
* Pass a `Settings` instance instead when a game wants to share deliberately
|
|
1636
|
+
* (a launcher and its titles), or drive them from its own store.
|
|
1637
|
+
*/
|
|
1638
|
+
settings?: Settings | {
|
|
1639
|
+
namespace: string;
|
|
1640
|
+
};
|
|
1603
1641
|
}
|
|
1604
1642
|
/**
|
|
1605
1643
|
* The game loop: drives a Scene's tree with fixed-timestep `fixedUpdate`
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { d as computeViewport, f as resolveViewport, k as diagnose, n as loadScene, z as registerBehavior } from "./loader-
|
|
3
|
-
import { _ as AudioPlayer, v as Engine } from "./register-
|
|
2
|
+
import { d as computeViewport, f as resolveViewport, k as diagnose, n as loadScene, z as registerBehavior } from "./loader-KZESOZmE.js";
|
|
3
|
+
import { _ as AudioPlayer, v as Engine } from "./register-Cs53CY7s.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { n as attachTouchControls } from "./touch-DEAmqGdf.js";
|
|
6
|
+
import { t as resolveRendering } from "./rendering-options-ByAdi8PF.js";
|
|
7
|
+
import { a as openBundledEditor, c as claimCanvasGestures, i as devServerLibrary, l as audioErrors, n as pauseWhenHidden, r as crossFade, s as wireDevChannel, t as teardown } from "./teardown-LB9cTnXJ.js";
|
|
7
8
|
import { o as frameStats } from "./frame-report-BSMny7oe.js";
|
|
8
|
-
import { n as registerGameplayBehaviors } from "./gameplay-
|
|
9
|
-
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-
|
|
9
|
+
import { n as registerGameplayBehaviors } from "./gameplay-CGSv-9XR.js";
|
|
10
|
+
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-vIxU3Xbv.js";
|
|
10
11
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
11
|
-
import { n as enablePhysics2D } from "./physics-2d-
|
|
12
|
+
import { n as enablePhysics2D } from "./physics-2d-_B6zj3zU.js";
|
|
12
13
|
import { Box3, BufferAttribute, BufferGeometry, Color, LineBasicMaterial, LineSegments, LinearFilter, NearestFilter, OrthographicCamera, Raycaster, SRGBColorSpace, Scene, TextureLoader, Vector2, Vector3, WebGLRenderer } from "three";
|
|
13
14
|
//#region src/2d/assets.ts
|
|
14
15
|
/**
|
|
@@ -756,6 +757,7 @@ async function createGame2D(opts) {
|
|
|
756
757
|
const engine = new Engine({
|
|
757
758
|
seed: opts.seed,
|
|
758
759
|
fixedHz: opts.fixedHz,
|
|
760
|
+
...opts.settings ? { settings: opts.settings } : {},
|
|
759
761
|
...opts._scheduler ? { scheduler: opts._scheduler } : {}
|
|
760
762
|
});
|
|
761
763
|
const sourceJson = cloneSceneJson(opts.scene);
|
|
@@ -918,7 +920,11 @@ async function createGame2D(opts) {
|
|
|
918
920
|
}
|
|
919
921
|
return {
|
|
920
922
|
engine,
|
|
921
|
-
scene
|
|
923
|
+
get scene() {
|
|
924
|
+
const live = engine.scene;
|
|
925
|
+
if (!live) throw new IncantoError("TREE_VIOLATION", "game.scene: the engine has no scene.");
|
|
926
|
+
return live;
|
|
927
|
+
},
|
|
922
928
|
sourceJson,
|
|
923
929
|
renderer,
|
|
924
930
|
physics,
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { c as parseEnvironment3D, k as diagnose, n as loadScene, s as horizonColorFromSky, u as sunDirectionFromSky, z as registerBehavior } from "./loader-
|
|
3
|
-
import { C as qualityRendering, _ as AudioPlayer, v as Engine, x as qualityCaps } from "./register-
|
|
2
|
+
import { c as parseEnvironment3D, k as diagnose, n as loadScene, s as horizonColorFromSky, u as sunDirectionFromSky, z as registerBehavior } from "./loader-KZESOZmE.js";
|
|
3
|
+
import { C as qualityRendering, _ as AudioPlayer, v as Engine, x as qualityCaps } from "./register-Cs53CY7s.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { n as attachTouchControls } from "./touch-DEAmqGdf.js";
|
|
6
|
+
import { t as resolveRendering } from "./rendering-options-ByAdi8PF.js";
|
|
7
|
+
import { a as openBundledEditor, c as claimCanvasGestures, i as devServerLibrary, l as audioErrors, n as pauseWhenHidden, o as poseFromRenderer, r as crossFade, s as wireDevChannel, t as teardown } from "./teardown-LB9cTnXJ.js";
|
|
7
8
|
import { o as frameStats } from "./frame-report-BSMny7oe.js";
|
|
8
|
-
import { J as createCausticsQuad, K as Node3D, U as PhysicsBody3D, n as registerGameplayBehaviors } from "./gameplay-
|
|
9
|
+
import { J as createCausticsQuad, K as Node3D, U as PhysicsBody3D, n as registerGameplayBehaviors } from "./gameplay-CGSv-9XR.js";
|
|
9
10
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
10
|
-
import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-
|
|
11
|
-
import { n as enablePhysics3D } from "./physics-3d-
|
|
11
|
+
import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-C-5g2pMh.js";
|
|
12
|
+
import { n as enablePhysics3D } from "./physics-3d-i1IeAY0F.js";
|
|
12
13
|
import { ACESFilmicToneMapping, AmbientLight, Box3, BufferAttribute, BufferGeometry, Color, DepthTexture, EquirectangularReflectionMapping, FloatType, Fog, HalfFloatType, LineBasicMaterial, LineSegments, Matrix4, Mesh, PCFShadowMap, PMREMGenerator, PerspectiveCamera, PlaneGeometry, Quaternion, Raycaster, Scene, ShaderMaterial, Vector2, Vector3, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
13
14
|
import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
|
|
14
15
|
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -27,6 +28,31 @@ import { Sky } from "three/examples/jsm/objects/Sky.js";
|
|
|
27
28
|
*/
|
|
28
29
|
var AssetStore3D = class {
|
|
29
30
|
engine;
|
|
31
|
+
/**
|
|
32
|
+
* One geometry and one material per distinct SHAPE and per distinct look.
|
|
33
|
+
*
|
|
34
|
+
* `MeshInstance3D._createObject3D` used to `new BoxGeometry()` and
|
|
35
|
+
* `new MeshPhysicalMaterial()` for every node, even when byte-identical.
|
|
36
|
+
* Three identical nodes reported `geometry shared? false false / material
|
|
37
|
+
* shared? false false`, with distinct uuids. Measured at 3,200 units, all
|
|
38
|
+
* three runs at identical 3,209 draw calls / 1,741,932 triangles and an
|
|
39
|
+
* identical screenshot:
|
|
40
|
+
*
|
|
41
|
+
* ```
|
|
42
|
+
* per-node geometry + material 31.0 ms wall (renderMs 27.3)
|
|
43
|
+
* share one geometry 27.0 ms
|
|
44
|
+
* + share two materials 15.4 ms <- 2x the headroom
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* 13.1 ms of that 26.5 ms cliff was GPU state churn from per-node objects,
|
|
48
|
+
* and none of it was visible headlessly: with no renderer `_syncObject3D`
|
|
49
|
+
* never runs, so the bench measured 55 ns/node instead of ~2,000.
|
|
50
|
+
*
|
|
51
|
+
* Renderer-scoped, deliberately — module-level state is the predecessor's
|
|
52
|
+
* fatal flaw and two games in one page must not share a cache.
|
|
53
|
+
*/
|
|
54
|
+
meshGeometries = /* @__PURE__ */ new Map();
|
|
55
|
+
meshMaterials = /* @__PURE__ */ new Map();
|
|
30
56
|
models = /* @__PURE__ */ new Map();
|
|
31
57
|
animations = /* @__PURE__ */ new Map();
|
|
32
58
|
modelKeys = /* @__PURE__ */ new Map();
|
|
@@ -253,10 +279,27 @@ function yieldToFrame(maxWaitMs = DEFAULT_MAX_WAIT_MS, raf = typeof requestAnima
|
|
|
253
279
|
* - hard-validates the merged result NOW (in your call stack), so a bad patch
|
|
254
280
|
* throws where you wrote it — never inside the render loop
|
|
255
281
|
*/
|
|
256
|
-
|
|
282
|
+
/**
|
|
283
|
+
* The environment stages a quality tier is allowed to touch.
|
|
284
|
+
*
|
|
285
|
+
* These are the ones `qualityEnvironment` names, and the ones that must snap
|
|
286
|
+
* back to what the scene file says rather than accumulating.
|
|
287
|
+
*/
|
|
288
|
+
const TIER_KEYS = [
|
|
289
|
+
"shadows",
|
|
290
|
+
"bloom",
|
|
291
|
+
"post",
|
|
292
|
+
"clouds"
|
|
293
|
+
];
|
|
294
|
+
function setEnvironment3D(engine, patch, opts) {
|
|
257
295
|
const scene = engine.scene;
|
|
258
296
|
if (!scene) throw new IncantoError("BAD_FORMAT", "setEnvironment3D: the engine has no scene.");
|
|
259
297
|
const merged = { ...scene.environment ?? {} };
|
|
298
|
+
if (opts?.rebaseTierKeys) {
|
|
299
|
+
const authored = scene.source?.environment ?? {};
|
|
300
|
+
for (const key of TIER_KEYS) if (key in authored) merged[key] = authored[key];
|
|
301
|
+
else delete merged[key];
|
|
302
|
+
}
|
|
260
303
|
for (const [key, value] of Object.entries(patch)) if (value === null) delete merged[key];
|
|
261
304
|
else if (typeof value === "object" && !Array.isArray(value) && typeof merged[key] === "object" && merged[key] !== null && !Array.isArray(merged[key])) merged[key] = {
|
|
262
305
|
...merged[key],
|
|
@@ -266,6 +309,24 @@ function setEnvironment3D(engine, patch) {
|
|
|
266
309
|
parseEnvironment3D(merged);
|
|
267
310
|
scene.environment = merged;
|
|
268
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* Apply a quality tier — the only caller that may RESET as well as patch.
|
|
314
|
+
*
|
|
315
|
+
* A tier is re-applied every time the player moves the slider, so it cannot
|
|
316
|
+
* compose with what the last one left behind: `low` strips the author's bloom,
|
|
317
|
+
* and `high` then has nothing to put back. This re-derives the four tier-owned
|
|
318
|
+
* stages from the scene FILE first, so every tier is reversible, and so a stage
|
|
319
|
+
* the author never wrote can never appear — the contract `settings.ts` states
|
|
320
|
+
* and `incanto-performance.md` promises: *the tier can only take things away.*
|
|
321
|
+
*
|
|
322
|
+
* Measured before this, on a scene with no `bloom` and no `post` in its JSON:
|
|
323
|
+
* `high` and `medium` both rendered five GL passes at 3.3 ms where `low`
|
|
324
|
+
* rendered one at 1.24 ms — 62% of the frame on a chain the game never asked
|
|
325
|
+
* for, and `environment.bloom` read back `{strength: 0.8, threshold: 1}`.
|
|
326
|
+
*/
|
|
327
|
+
function applyQualityTier3D(engine, patch) {
|
|
328
|
+
setEnvironment3D(engine, patch, { rebaseTierKeys: true });
|
|
329
|
+
}
|
|
269
330
|
//#endregion
|
|
270
331
|
//#region src/3d/adaptive-resolution.ts
|
|
271
332
|
const DEFAULTS = {
|
|
@@ -2180,6 +2241,7 @@ async function createGame3D(opts) {
|
|
|
2180
2241
|
const engine = new Engine({
|
|
2181
2242
|
seed: opts.seed,
|
|
2182
2243
|
fixedHz: opts.fixedHz,
|
|
2244
|
+
...opts.settings ? { settings: opts.settings } : {},
|
|
2183
2245
|
...opts._scheduler ? { scheduler: opts._scheduler } : {}
|
|
2184
2246
|
});
|
|
2185
2247
|
const sourceJson = cloneSceneJson(opts.scene);
|
|
@@ -2294,7 +2356,7 @@ async function createGame3D(opts) {
|
|
|
2294
2356
|
cleanups.push(engine.settings.bindAudio(engine.audio));
|
|
2295
2357
|
cleanups.push(engine.settings.bindLocale(engine.locale));
|
|
2296
2358
|
cleanups.push(engine.settings.bindQuality((patch) => {
|
|
2297
|
-
|
|
2359
|
+
applyQualityTier3D(engine, patch);
|
|
2298
2360
|
}));
|
|
2299
2361
|
cleanups.push(engine.settings.bindFrameCap((fps) => {
|
|
2300
2362
|
engine.maxFps = fps;
|
|
@@ -2368,7 +2430,11 @@ async function createGame3D(opts) {
|
|
|
2368
2430
|
}
|
|
2369
2431
|
return {
|
|
2370
2432
|
engine,
|
|
2371
|
-
scene
|
|
2433
|
+
get scene() {
|
|
2434
|
+
const live = engine.scene;
|
|
2435
|
+
if (!live) throw new IncantoError("TREE_VIOLATION", "game.scene: the engine has no scene.");
|
|
2436
|
+
return live;
|
|
2437
|
+
},
|
|
2372
2438
|
sourceJson,
|
|
2373
2439
|
renderer,
|
|
2374
2440
|
physics,
|
|
@@ -2454,4 +2520,4 @@ function wireAudioUnlock(engine, root, canvas) {
|
|
|
2454
2520
|
return detachAll;
|
|
2455
2521
|
}
|
|
2456
2522
|
//#endregion
|
|
2457
|
-
export { Environment3D as a, syncTree as i, create_game_exports as n,
|
|
2523
|
+
export { Environment3D as a, AssetStore3D as c, syncTree as i, create_game_exports as n, applyQualityTier3D as o, Renderer3D as r, setEnvironment3D as s, createGame3D as t };
|
package/dist/debug.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ft as LogLevel, T as RendererStats, b as Engine } from "./behavior-
|
|
1
|
+
import { Ft as LogLevel, T as RendererStats, b as Engine } from "./behavior-ZnfzKDo3.js";
|
|
2
2
|
|
|
3
3
|
//#region src/debug/panel.d.ts
|
|
4
4
|
/** Minimal document surface the overlay needs (injectable for tests). */
|
package/dist/debug.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { t as jsonClone } from "./json-CwwhxQgb.js";
|
|
2
2
|
import { s as mergeStaticProps } from "./registry-CF70EArN.js";
|
|
3
|
+
import { r as capturePointer } from "./touch-DEAmqGdf.js";
|
|
3
4
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
4
5
|
//#region src/debug/capture.ts
|
|
5
6
|
/**
|
|
@@ -369,7 +370,7 @@ var FloatingPanel = class {
|
|
|
369
370
|
active = e.pointerId;
|
|
370
371
|
lastX = e.clientX;
|
|
371
372
|
lastY = e.clientY;
|
|
372
|
-
grip
|
|
373
|
+
capturePointer(grip, e.pointerId);
|
|
373
374
|
});
|
|
374
375
|
grip.addEventListener("pointermove", (e) => {
|
|
375
376
|
if (e.pointerId !== active) return;
|
|
@@ -565,7 +566,7 @@ function openRegionSelect(opts) {
|
|
|
565
566
|
applyStyle(popup, { display: "none" });
|
|
566
567
|
applyStyle(box, { cursor: next === "move" ? "grabbing" : "crosshair" });
|
|
567
568
|
const id = event.pointerId;
|
|
568
|
-
if (id !== void 0) layer
|
|
569
|
+
if (id !== void 0) capturePointer(layer, id);
|
|
569
570
|
render();
|
|
570
571
|
}
|
|
571
572
|
function render() {
|
package/dist/editor.js
CHANGED
|
@@ -2380,7 +2380,8 @@ var Vn = [
|
|
|
2380
2380
|
"connections",
|
|
2381
2381
|
"input",
|
|
2382
2382
|
"multiplayer",
|
|
2383
|
-
"strings"
|
|
2383
|
+
"strings",
|
|
2384
|
+
"environment"
|
|
2384
2385
|
];
|
|
2385
2386
|
function Hn(e, t, n) {
|
|
2386
2387
|
e.appendChild(Tr("scene")), e.appendChild(Ar("name", String(t.working.name ?? ""), (e) => {
|
|
@@ -7842,6 +7843,10 @@ var ss = class {
|
|
|
7842
7843
|
return !0;
|
|
7843
7844
|
}) === !0;
|
|
7844
7845
|
}
|
|
7846
|
+
resume(e) {
|
|
7847
|
+
let t = this.original;
|
|
7848
|
+
this.reset(e), this.original = t;
|
|
7849
|
+
}
|
|
7845
7850
|
reset(e) {
|
|
7846
7851
|
this.working = e, this.working.root && cs(this.working.root), this.original = JSON.stringify(this.working), this.undoStack = [], this.selection = [], this.emit();
|
|
7847
7852
|
}
|
|
@@ -9794,7 +9799,7 @@ async function xc(e = {}) {
|
|
|
9794
9799
|
let t = e.target.matches("input, textarea, select");
|
|
9795
9800
|
(e.metaKey || e.ctrlKey) && e.key === "z" ? (e.preventDefault(), u.undo()) : (e.metaKey || e.ctrlKey) && e.key === "s" ? (e.preventDefault(), p.disabled || p.click()) : !t && e.code === "KeyF" ? P.zoomToFit() : !t && (e.code === "Digit0" || e.code === "Numpad0") ? P.gameView() : !t && e.code === "KeyW" ? P.setMode("move") : !t && e.code === "KeyE" ? P.setMode("rotate") : !t && e.code === "KeyR" && P.setMode("scale");
|
|
9796
9801
|
};
|
|
9797
|
-
return window.addEventListener("keydown", Me), n.push(() => window.removeEventListener("keydown", Me)), F(), e.camera && P.setEditCamera(e.camera.position, e.camera.target), kt.ready(C, w, o.version), {
|
|
9802
|
+
return window.addEventListener("keydown", Me), n.push(() => window.removeEventListener("keydown", Me)), F(), e.scene && u.resume(e.scene), e.camera && P.setEditCamera(e.camera.position, e.camera.target), kt.ready(C, w, o.version), {
|
|
9798
9803
|
working: () => u.working,
|
|
9799
9804
|
camera: () => P.editCamera(),
|
|
9800
9805
|
showError: O,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { k as diagnose } from "./loader-
|
|
2
|
-
import { L as translateOn, t as registerCoreNodes } from "./register-
|
|
1
|
+
import { k as diagnose } from "./loader-KZESOZmE.js";
|
|
2
|
+
import { L as translateOn, t as registerCoreNodes } from "./register-Cs53CY7s.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
5
5
|
import { i as getNodeSchema, l as registerNode } from "./registry-CF70EArN.js";
|
|
6
6
|
import { t as createNoise2D } from "./noise-CGUMx44x.js";
|
|
7
7
|
import { i as ParticleSim, n as resolveFrames, o as PARTICLE_PRESET_NAMES, r as validateAnimationAliases, s as applyParticlePreset, t as resolveAnimation } from "./sprite-animation-CY-mrr1L.js";
|
|
8
|
-
import { B as rejectScale, G as StaticBody3D, H as CharacterBody3D, K as Node3D, L as Water3D, U as PhysicsBody3D, V as Area3D, W as RigidBody3D, X as colliderFootDrop, w as tolerateUnknownAction, z as WaterCutout3D } from "./gameplay-
|
|
8
|
+
import { B as rejectScale, G as StaticBody3D, H as CharacterBody3D, K as Node3D, L as Water3D, U as PhysicsBody3D, V as Area3D, W as RigidBody3D, X as colliderFootDrop, w as tolerateUnknownAction, z as WaterCutout3D } from "./gameplay-CGSv-9XR.js";
|
|
9
9
|
import { t as checkSheetGrid } from "./sheet-grid-BT6N_Bjs.js";
|
|
10
10
|
import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
|
|
11
11
|
import { AdditiveBlending, AnimationClip, AnimationMixer, Box3, BoxGeometry, BufferAttribute, BufferGeometry, CanvasTexture, CapsuleGeometry, ClampToEdgeWrapping, Color, ConeGeometry, CylinderGeometry, DataTexture, DirectionalLight, DoubleSide, DynamicDrawUsage, Euler, Group, IcosahedronGeometry, ImageBitmapLoader, InstancedBufferAttribute, InstancedMesh, LinearFilter, LinearMipmapLinearFilter, LoopOnce, LoopRepeat, Matrix4, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshPhysicalMaterial, MeshStandardMaterial, NearestFilter, NoBlending, NoColorSpace, NormalBlending, PerspectiveCamera, PlaneGeometry, PointLight, Points, PointsMaterial, Quaternion, QuaternionKeyframeTrack, RGBADepthPacking, RGBAFormat, RepeatWrapping, SRGBColorSpace, ShaderChunk, ShaderMaterial, SphereGeometry, Texture, TextureLoader, UniformsLib, UniformsUtils, Vector3, Vector4, VectorKeyframeTrack } from "three";
|
|
@@ -387,6 +387,10 @@ var MeshInstance3D = class extends Node3D {
|
|
|
387
387
|
validateMeshMaterial(node.material, node.name);
|
|
388
388
|
}
|
|
389
389
|
geometryKey = "";
|
|
390
|
+
materialKey = "";
|
|
391
|
+
/** True while this node is using a cache entry it must not dispose. */
|
|
392
|
+
sharedGeometry = false;
|
|
393
|
+
sharedMaterial = false;
|
|
390
394
|
textureKey = "";
|
|
391
395
|
loadedTextures = [];
|
|
392
396
|
_createObject3D() {
|
|
@@ -395,12 +399,48 @@ var MeshInstance3D = class extends Node3D {
|
|
|
395
399
|
_syncObject3D(alpha = 1, assets = null) {
|
|
396
400
|
super._syncObject3D(alpha, assets);
|
|
397
401
|
const m = this._ensureObject3D();
|
|
398
|
-
const key = `${this.mesh}:${
|
|
402
|
+
const key = `${this.mesh}:${this.size.join(",")}`;
|
|
399
403
|
if (key !== this.geometryKey) {
|
|
400
|
-
m.geometry.dispose();
|
|
401
|
-
|
|
404
|
+
if (!this.sharedGeometry) m.geometry.dispose();
|
|
405
|
+
const cached = assets?.meshGeometries.get(key);
|
|
406
|
+
if (cached) {
|
|
407
|
+
m.geometry = cached;
|
|
408
|
+
this.sharedGeometry = true;
|
|
409
|
+
} else {
|
|
410
|
+
const built = buildMeshGeometry(this.mesh, this.size);
|
|
411
|
+
m.geometry = built;
|
|
412
|
+
this.sharedGeometry = Boolean(assets);
|
|
413
|
+
assets?.meshGeometries.set(key, built);
|
|
414
|
+
}
|
|
402
415
|
this.geometryKey = key;
|
|
403
416
|
}
|
|
417
|
+
const look = JSON.stringify(this.material);
|
|
418
|
+
if (assets && look !== this.materialKey) {
|
|
419
|
+
const shared = assets.meshMaterials.get(look);
|
|
420
|
+
if (shared) {
|
|
421
|
+
if (!this.sharedMaterial) m.material.dispose();
|
|
422
|
+
m.material = shared;
|
|
423
|
+
this.sharedMaterial = true;
|
|
424
|
+
this.materialKey = look;
|
|
425
|
+
this.textureKey = "shared";
|
|
426
|
+
m.castShadow = this.castShadow;
|
|
427
|
+
m.receiveShadow = this.receiveShadow;
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
if (this.sharedMaterial) {
|
|
431
|
+
m.material = new MeshPhysicalMaterial();
|
|
432
|
+
this.sharedMaterial = false;
|
|
433
|
+
this.textureKey = "";
|
|
434
|
+
}
|
|
435
|
+
this.materialKey = look;
|
|
436
|
+
const mine = m.material;
|
|
437
|
+
applyMeshMaterial(mine, this.material);
|
|
438
|
+
this.syncTextures(mine, assets);
|
|
439
|
+
assets.meshMaterials.set(look, mine);
|
|
440
|
+
m.castShadow = this.castShadow;
|
|
441
|
+
m.receiveShadow = this.receiveShadow;
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
404
444
|
const mat = m.material;
|
|
405
445
|
applyMeshMaterial(mat, this.material);
|
|
406
446
|
this.syncTextures(mat, assets);
|