incanto 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/3d.d.ts +40 -11
- package/dist/3d.js +3 -3
- package/dist/{create-game-J6g4QInv.js → create-game-BS-K-GY1.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{physics-3d-DhaAaKJo.js → physics-3d-TmOuCy7J.js} +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-BFw4c83z.js → register-Bh_3Z39N.js} +164 -39
- package/dist/test.js +3 -3
- package/editor/assets/{agent8-BF8Jfbkl.js → agent8-DqQ2CQ5A.js} +1 -1
- package/editor/assets/{index-DSq0gdhE.js → index-CofH0yGY.js} +79 -7
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +19 -6
- package/skills/incanto-environment.md +22 -17
- package/skills/incanto-node-reference.md +7 -3
- package/templates-app/beacon-isle-3d/PROJECT/Status.md +1 -1
- package/templates-app/beacon-isle-3d/generate-world.ts +23 -20
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/beacon-isle-3d/src/behaviors.ts +70 -4
- package/templates-app/beacon-isle-3d/src/game.scene.json +43 -67
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/PROJECT/Context.md +1 -1
- package/templates-app/village-quest-3d/PROJECT/Requirements.md +1 -1
- package/templates-app/village-quest-3d/PROJECT/Structure.md +6 -1
- package/templates-app/village-quest-3d/generate-dressing.ts +769 -0
- package/templates-app/village-quest-3d/package.json +1 -1
- package/templates-app/village-quest-3d/src/behaviors.ts +74 -8
- package/templates-app/village-quest-3d/src/grove.scene.json +1 -13
- package/templates-app/village-quest-3d/src/village.scene.json +2989 -162
package/dist/3d.d.ts
CHANGED
|
@@ -888,9 +888,13 @@ declare class Flowers3D extends Node3D {
|
|
|
888
888
|
clustering: number;
|
|
889
889
|
/** Gentle head-bob wind strength — 0 holds still. */
|
|
890
890
|
sway: number;
|
|
891
|
-
/**
|
|
892
|
-
*
|
|
893
|
-
|
|
891
|
+
/**
|
|
892
|
+
* null (the default) is AUTO: whenever the scene has a Terrain3D, instances
|
|
893
|
+
* root on it — flat ground behaves as before, rolling terrain just works.
|
|
894
|
+
* true forces it (keeps retrying until a terrain appears), false disables
|
|
895
|
+
* draping entirely.
|
|
896
|
+
*/
|
|
897
|
+
drape: boolean | null;
|
|
894
898
|
/** Drape target: a node path to the Terrain3D. Empty = auto-find the first
|
|
895
899
|
* Terrain3D in the tree (the zero-config default when `drape` is on). */
|
|
896
900
|
terrain: string;
|
|
@@ -1025,9 +1029,14 @@ declare class Foliage3D extends Node3D implements SunConsumer3D {
|
|
|
1025
1029
|
flowers: number;
|
|
1026
1030
|
/** Placement seed — the field is identical across runs and machines. */
|
|
1027
1031
|
seed: number;
|
|
1028
|
-
/**
|
|
1029
|
-
*
|
|
1030
|
-
|
|
1032
|
+
/**
|
|
1033
|
+
* Drape each instance onto a Terrain3D's surface so blades root on the
|
|
1034
|
+
* ground instead of a flat plane. null (the default) is AUTO: whenever the
|
|
1035
|
+
* scene has a Terrain3D, instances root on it — flat ground behaves as
|
|
1036
|
+
* before, rolling terrain just works. true forces it (keeps retrying until
|
|
1037
|
+
* a terrain appears), false disables draping entirely.
|
|
1038
|
+
*/
|
|
1039
|
+
drape: boolean | null;
|
|
1031
1040
|
/** Drape target: a node path to the Terrain3D. Empty = auto-find the first
|
|
1032
1041
|
* Terrain3D in the tree (the zero-config default when `drape` is on). */
|
|
1033
1042
|
terrain: string;
|
|
@@ -1061,6 +1070,8 @@ declare class Foliage3D extends Node3D implements SunConsumer3D {
|
|
|
1061
1070
|
/** @internal Every InstancedMesh of the field: [quads] or [quads, quads90°]. */
|
|
1062
1071
|
_fields(): InstancedMesh[];
|
|
1063
1072
|
override update(dt: number): void;
|
|
1073
|
+
/** Wind time/strength + the ≤4 character-bend slots (no-op before first build). */
|
|
1074
|
+
private writeAnimationUniforms;
|
|
1064
1075
|
override _syncObject3D(): void;
|
|
1065
1076
|
/**
|
|
1066
1077
|
* @internal Environment-sky sun hand-off (see {@link SunConsumer3D}): the
|
|
@@ -1821,11 +1832,14 @@ declare class Tree3D extends Node3D {
|
|
|
1821
1832
|
/** Let leaves cast shadows. false keeps trunk/branch shadows but drops the
|
|
1822
1833
|
* expensive alpha-cutout leaf shadow pass (the dappled floor) for big FPS. */
|
|
1823
1834
|
leafShadows: boolean;
|
|
1824
|
-
/**
|
|
1825
|
-
*
|
|
1826
|
-
*
|
|
1827
|
-
*
|
|
1828
|
-
|
|
1835
|
+
/**
|
|
1836
|
+
* Drape the grove over a Terrain3D: each scattered instance roots at the
|
|
1837
|
+
* ground height under it (not the node's single Y), so a patch on rolling
|
|
1838
|
+
* or carved terrain never floats/buries. null (the default) is AUTO:
|
|
1839
|
+
* whenever the scene has a Terrain3D the grove drapes onto it. true forces
|
|
1840
|
+
* it (keeps retrying until a terrain appears), false disables draping.
|
|
1841
|
+
*/
|
|
1842
|
+
drape: boolean | null;
|
|
1829
1843
|
/** Node path to the Terrain3D to drape onto ('' = auto-find the first one). */
|
|
1830
1844
|
terrain: string;
|
|
1831
1845
|
/** Resolved drape target + the grove's world position, set per rebuild. */
|
|
@@ -2029,6 +2043,21 @@ declare class Water3D extends Node3D implements RenderHook3D, SunConsumer3D {
|
|
|
2029
2043
|
* `{ color?, visibility? }` overrides the fog hue / view distance (meters).
|
|
2030
2044
|
*/
|
|
2031
2045
|
underwater: boolean | JsonObject;
|
|
2046
|
+
/**
|
|
2047
|
+
* Directional traveling SWELL amplitude in meters (fancy only; 0 = off, the
|
|
2048
|
+
* legacy isotropic look). Three peaked wave trains march across the surface
|
|
2049
|
+
* at real deep-water speeds — THE open-ocean dial: 0.15 = lively lake chop,
|
|
2050
|
+
* 0.4 = coastal sea, 0.8 = heavy weather. Crests feed the color ramp,
|
|
2051
|
+
* `whitecaps` and the shore foam automatically.
|
|
2052
|
+
*/
|
|
2053
|
+
swell: number;
|
|
2054
|
+
/** Compass direction the swell TRAVELS toward, degrees (0 = +z, 90 = +x). */
|
|
2055
|
+
swellDirectionDeg: number;
|
|
2056
|
+
/** Primary swell wavelength in meters (the two crossing trains derive). */
|
|
2057
|
+
swellWavelength: number;
|
|
2058
|
+
/** Open-water whitecap foam on the tallest crests, 0–1 (fancy only). Works
|
|
2059
|
+
* best with `swell` — the caps ride the swell's crest lines. */
|
|
2060
|
+
whitecaps: number;
|
|
2032
2061
|
/** Loader hook: degenerate planes and bad enums fail at LOAD, not at render. */
|
|
2033
2062
|
static validateJson(node: Node): void;
|
|
2034
2063
|
private time;
|
package/dist/3d.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
2
|
-
import { a as Environment3D, c as sunDirectionFromElevationAzimuth, i as syncTree, l as sunDirectionFromSky, o as horizonColorFromSky, r as Renderer3D, s as parseEnvironment3D, t as createGame3D, u as AssetStore3D } from "./create-game-
|
|
3
|
-
import { A as Area3D, B as movementState, C as BoneAttachment3D, D as TERRAIN_THEMES, E as DEFAULT_TERRAIN_TEXTURE_BASE, F as Node3D, L as QUARTER_PITCH, M as PhysicsBody3D, N as RigidBody3D, O as terrainThemeLayers, P as StaticBody3D, R as cameraRelative, S as BoneLookAt3D, T as Terrain3D, V as rigPose, _ as Flowers3D, a as VoxelGrid3D, b as CharacterController3D, c as Particles3D, d as DirectionalLight3D, f as OmniLight3D, g as DENSITY_PRESETS, h as Foliage3D, i as VOXEL_PALETTE, j as CharacterBody3D, k as Joint3D, l as ModelInstance3D, m as MeshInstance3D, n as Water3D, o as Tree3D, p as InstancedMesh3D, r as WATER_MAX_RIPPLES, s as Trail3D, t as registerNodes3D, u as LoftMesh3D, v as resolveFlowerDensity, w as Billboard3D, x as Camera3D, y as FLOWER_VARIETIES, z as keyboardIntensity } from "./register-
|
|
2
|
+
import { a as Environment3D, c as sunDirectionFromElevationAzimuth, i as syncTree, l as sunDirectionFromSky, o as horizonColorFromSky, r as Renderer3D, s as parseEnvironment3D, t as createGame3D, u as AssetStore3D } from "./create-game-BS-K-GY1.js";
|
|
3
|
+
import { A as Area3D, B as movementState, C as BoneAttachment3D, D as TERRAIN_THEMES, E as DEFAULT_TERRAIN_TEXTURE_BASE, F as Node3D, L as QUARTER_PITCH, M as PhysicsBody3D, N as RigidBody3D, O as terrainThemeLayers, P as StaticBody3D, R as cameraRelative, S as BoneLookAt3D, T as Terrain3D, V as rigPose, _ as Flowers3D, a as VoxelGrid3D, b as CharacterController3D, c as Particles3D, d as DirectionalLight3D, f as OmniLight3D, g as DENSITY_PRESETS, h as Foliage3D, i as VOXEL_PALETTE, j as CharacterBody3D, k as Joint3D, l as ModelInstance3D, m as MeshInstance3D, n as Water3D, o as Tree3D, p as InstancedMesh3D, r as WATER_MAX_RIPPLES, s as Trail3D, t as registerNodes3D, u as LoftMesh3D, v as resolveFlowerDensity, w as Billboard3D, x as Camera3D, y as FLOWER_VARIETIES, z as keyboardIntensity } from "./register-Bh_3Z39N.js";
|
|
4
4
|
import { n as splatWeights, t as buildHeightmap } from "./heightmap-CroQPEER.js";
|
|
5
|
-
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-
|
|
5
|
+
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-TmOuCy7J.js";
|
|
6
6
|
//#region src/3d/environment-runtime.ts
|
|
7
7
|
/**
|
|
8
8
|
* Live environment editing — the renderer re-applies `scene.environment`
|
|
@@ -5,8 +5,8 @@ import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
|
5
5
|
import { i as resolveRendering, n as attachTouchControls } from "./touch-031PxtCR.js";
|
|
6
6
|
import { n as registerGameplayBehaviors } from "./gameplay-sSqrUcnz.js";
|
|
7
7
|
import { t as debugSources } from "./debug-draw-CZmOYjL2.js";
|
|
8
|
-
import { F as Node3D, M as PhysicsBody3D, d as DirectionalLight3D, l as ModelInstance3D, t as registerNodes3D, x as Camera3D } from "./register-
|
|
9
|
-
import { n as enablePhysics3D } from "./physics-3d-
|
|
8
|
+
import { F as Node3D, M as PhysicsBody3D, d as DirectionalLight3D, l as ModelInstance3D, t as registerNodes3D, x as Camera3D } from "./register-Bh_3Z39N.js";
|
|
9
|
+
import { n as enablePhysics3D } from "./physics-3d-TmOuCy7J.js";
|
|
10
10
|
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";
|
|
11
11
|
import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
|
|
12
12
|
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
package/dist/index.js
CHANGED
|
@@ -295,6 +295,6 @@ function newUid() {
|
|
|
295
295
|
//#endregion
|
|
296
296
|
//#region src/index.ts
|
|
297
297
|
/** Engine version. Kept in sync with package.json by the release pipeline. */
|
|
298
|
-
const VERSION = "0.
|
|
298
|
+
const VERSION = "0.15.0";
|
|
299
299
|
//#endregion
|
|
300
300
|
export { AudioBuses, AudioPlayer, Behavior, CONST_REF_KEY, Engine, HudLayer, IncantoError, InputMap, LogManager, MusicManager, Node, ORDER_GROUP_BASE, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, ParticleSim, ROLLOFF_MODELS, Rng, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, Scene, SceneTree, SfxEngine, Signal, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiText, VERSION, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, mergeStaticSignals, newUid, parseNodePath, preloadUrls, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveConstants, resolveRendering, resolveViewport, serializeNode, spatialGain, spatialPan, startRecording, synthSfx };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
2
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
3
3
|
import { n as registerDebugSource } from "./debug-draw-CZmOYjL2.js";
|
|
4
|
-
import { A as Area3D, F as Node3D, I as validateCollider3D, M as PhysicsBody3D, N as RigidBody3D, T as Terrain3D, j as CharacterBody3D, k as Joint3D } from "./register-
|
|
4
|
+
import { A as Area3D, F as Node3D, I as validateCollider3D, M as PhysicsBody3D, N as RigidBody3D, T as Terrain3D, j as CharacterBody3D, k as Joint3D } from "./register-Bh_3Z39N.js";
|
|
5
5
|
import { Euler, Quaternion } from "three";
|
|
6
6
|
//#region src/3d/physics/physics-3d.ts
|
|
7
7
|
var physics_3d_exports = /* @__PURE__ */ __exportAll({
|
package/dist/react.js
CHANGED
|
@@ -156,7 +156,7 @@ function IncantoCanvas(props) {
|
|
|
156
156
|
pointer: latest.pointer,
|
|
157
157
|
...keyboard !== void 0 ? { keyboard } : {}
|
|
158
158
|
};
|
|
159
|
-
const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-
|
|
159
|
+
const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-BS-K-GY1.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-Ct86zczq.js").then((n) => n.n)).createGame2D(o)))(opts);
|
|
160
160
|
if (disposed) {
|
|
161
161
|
next.dispose();
|
|
162
162
|
return;
|
|
@@ -3066,7 +3066,7 @@ var Flowers3D = class extends Node3D {
|
|
|
3066
3066
|
height: { default: .45 },
|
|
3067
3067
|
clustering: { default: .6 },
|
|
3068
3068
|
sway: { default: .5 },
|
|
3069
|
-
drape: { default:
|
|
3069
|
+
drape: { default: null },
|
|
3070
3070
|
terrain: { default: "" }
|
|
3071
3071
|
};
|
|
3072
3072
|
/** 'lush' | 'sparse' | 'none' | plants per m² (load-time check + budget). */
|
|
@@ -3087,9 +3087,13 @@ var Flowers3D = class extends Node3D {
|
|
|
3087
3087
|
clustering = .6;
|
|
3088
3088
|
/** Gentle head-bob wind strength — 0 holds still. */
|
|
3089
3089
|
sway = .5;
|
|
3090
|
-
/**
|
|
3091
|
-
*
|
|
3092
|
-
|
|
3090
|
+
/**
|
|
3091
|
+
* null (the default) is AUTO: whenever the scene has a Terrain3D, instances
|
|
3092
|
+
* root on it — flat ground behaves as before, rolling terrain just works.
|
|
3093
|
+
* true forces it (keeps retrying until a terrain appears), false disables
|
|
3094
|
+
* draping entirely.
|
|
3095
|
+
*/
|
|
3096
|
+
drape = null;
|
|
3093
3097
|
/** Drape target: a node path to the Terrain3D. Empty = auto-find the first
|
|
3094
3098
|
* Terrain3D in the tree (the zero-config default when `drape` is on). */
|
|
3095
3099
|
terrain = "";
|
|
@@ -3119,7 +3123,7 @@ var Flowers3D = class extends Node3D {
|
|
|
3119
3123
|
if (!(f.height > 0)) throw new IncantoError("BAD_FORMAT", `Flowers3D '${node.name}' height must be > 0 meters, got ${f.height}.`, { prop: "height" });
|
|
3120
3124
|
if (!(f.clustering >= 0) || !(f.clustering <= 1)) throw new IncantoError("BAD_FORMAT", `Flowers3D '${node.name}' clustering must be in [0, 1] (0 uniform … 1 tight patches), got ${f.clustering}.`, { prop: "clustering" });
|
|
3121
3125
|
if (!(f.sway >= 0)) throw new IncantoError("BAD_FORMAT", `Flowers3D '${node.name}' sway must be >= 0, got ${f.sway}.`, { prop: "sway" });
|
|
3122
|
-
if (typeof f.drape !== "boolean") throw new IncantoError("BAD_FORMAT", `Flowers3D '${node.name}' drape must be a
|
|
3126
|
+
if (f.drape !== null && typeof f.drape !== "boolean") throw new IncantoError("BAD_FORMAT", `Flowers3D '${node.name}' drape must be true, false or null (null = auto: drape whenever the scene has a Terrain3D), got ${JSON.stringify(f.drape)}.`, { prop: "drape" });
|
|
3123
3127
|
if (typeof f.terrain !== "string") throw new IncantoError("BAD_FORMAT", `Flowers3D '${node.name}' terrain must be a node-path string (empty = auto-find), got ${JSON.stringify(f.terrain)}.`, { prop: "terrain" });
|
|
3124
3128
|
}
|
|
3125
3129
|
time = 0;
|
|
@@ -3172,7 +3176,7 @@ var Flowers3D = class extends Node3D {
|
|
|
3172
3176
|
/** Resolve the drape target + cache the bed's world position for `bedY`. */
|
|
3173
3177
|
resolveDrape() {
|
|
3174
3178
|
this.drapeTerrain = null;
|
|
3175
|
-
if (
|
|
3179
|
+
if (this.drape === false) return;
|
|
3176
3180
|
const terrain = findDrapeTerrain(this, this.terrain);
|
|
3177
3181
|
if (terrain) {
|
|
3178
3182
|
this.drapeTerrain = terrain;
|
|
@@ -4449,7 +4453,7 @@ var Foliage3D = class Foliage3D extends Node3D {
|
|
|
4449
4453
|
coverage: { default: .85 },
|
|
4450
4454
|
flowers: { default: 0 },
|
|
4451
4455
|
seed: { default: 1 },
|
|
4452
|
-
drape: { default:
|
|
4456
|
+
drape: { default: null },
|
|
4453
4457
|
terrain: { default: "" },
|
|
4454
4458
|
renderOrder: { default: 2 }
|
|
4455
4459
|
};
|
|
@@ -4508,9 +4512,14 @@ var Foliage3D = class Foliage3D extends Node3D {
|
|
|
4508
4512
|
flowers = 0;
|
|
4509
4513
|
/** Placement seed — the field is identical across runs and machines. */
|
|
4510
4514
|
seed = 1;
|
|
4511
|
-
/**
|
|
4512
|
-
*
|
|
4513
|
-
|
|
4515
|
+
/**
|
|
4516
|
+
* Drape each instance onto a Terrain3D's surface so blades root on the
|
|
4517
|
+
* ground instead of a flat plane. null (the default) is AUTO: whenever the
|
|
4518
|
+
* scene has a Terrain3D, instances root on it — flat ground behaves as
|
|
4519
|
+
* before, rolling terrain just works. true forces it (keeps retrying until
|
|
4520
|
+
* a terrain appears), false disables draping entirely.
|
|
4521
|
+
*/
|
|
4522
|
+
drape = null;
|
|
4514
4523
|
/** Drape target: a node path to the Terrain3D. Empty = auto-find the first
|
|
4515
4524
|
* Terrain3D in the tree (the zero-config default when `drape` is on). */
|
|
4516
4525
|
terrain = "";
|
|
@@ -4544,7 +4553,7 @@ var Foliage3D = class Foliage3D extends Node3D {
|
|
|
4544
4553
|
if (!Array.isArray(sun) || sun.length !== 3 || !sun.every((v) => Number.isFinite(v)) || Math.hypot(sun[0] ?? 0, sun[1] ?? 0, sun[2] ?? 0) === 0) throw new IncantoError("BAD_FORMAT", `Foliage3D '${node.name}' sunDirection must be a non-zero [x, y, z] vector, got ${JSON.stringify(sun)}.`, { prop: "sunDirection" });
|
|
4545
4554
|
if (!(f.coverage > 0) || !(f.coverage <= 1)) throw new IncantoError("BAD_FORMAT", `Foliage3D '${node.name}' coverage must be in (0, 1] (carpet fill — 1 is solid, lower carves dirt patches), got ${f.coverage}.`, { prop: "coverage" });
|
|
4546
4555
|
if (!(f.flowers >= 0) || !(f.flowers <= .2)) throw new IncantoError("BAD_FORMAT", `Foliage3D '${node.name}' flowers must be in [0, 0.2] (fraction of instances rendered as flower heads — for a whole flower FIELD use kind: 'flowers'), got ${f.flowers}.`, { prop: "flowers" });
|
|
4547
|
-
if (typeof f.drape !== "boolean") throw new IncantoError("BAD_FORMAT", `Foliage3D '${node.name}' drape must be a
|
|
4556
|
+
if (f.drape !== null && typeof f.drape !== "boolean") throw new IncantoError("BAD_FORMAT", `Foliage3D '${node.name}' drape must be true, false or null (null = auto: drape whenever the scene has a Terrain3D), got ${JSON.stringify(f.drape)}.`, { prop: "drape" });
|
|
4548
4557
|
if (typeof f.terrain !== "string") throw new IncantoError("BAD_FORMAT", `Foliage3D '${node.name}' terrain must be a node-path string (empty = auto-find), got ${JSON.stringify(f.terrain)}.`, { prop: "terrain" });
|
|
4549
4558
|
}
|
|
4550
4559
|
time = 0;
|
|
@@ -4590,16 +4599,33 @@ var Foliage3D = class Foliage3D extends Node3D {
|
|
|
4590
4599
|
update(dt) {
|
|
4591
4600
|
this.time += dt;
|
|
4592
4601
|
this.pickedBenders = this.computeBenders();
|
|
4602
|
+
this.writeAnimationUniforms();
|
|
4603
|
+
}
|
|
4604
|
+
/** Wind time/strength + the ≤4 character-bend slots (no-op before first build). */
|
|
4605
|
+
writeAnimationUniforms() {
|
|
4606
|
+
if (this.isShaderField && this.bladesMaterial) {
|
|
4607
|
+
const u = this.bladesMaterial.uniforms;
|
|
4608
|
+
if (u.time) u.time.value = this.time;
|
|
4609
|
+
if (u.windStrength) u.windStrength.value = this.sway * (this.isMesh ? MESH_SWAY_TO_WIND : SWAY_TO_WIND);
|
|
4610
|
+
const slots = this.benderSlots;
|
|
4611
|
+
if (slots) for (let i = 0; i < 4; i++) {
|
|
4612
|
+
const b = this.pickedBenders[i];
|
|
4613
|
+
if (b) slots[i]?.set(b.x, b.y, b.z, b.radius);
|
|
4614
|
+
else slots[i]?.set(0, 0, 0, 0);
|
|
4615
|
+
}
|
|
4616
|
+
} else if (this.isTufts) {
|
|
4617
|
+
if (this.tuftTime) this.tuftTime.value = this.time;
|
|
4618
|
+
if (this.tuftStrength) this.tuftStrength.value = this.sway * TUFT_SWAY_TO_WIND;
|
|
4619
|
+
}
|
|
4593
4620
|
}
|
|
4594
4621
|
_syncObject3D() {
|
|
4595
4622
|
super._syncObject3D();
|
|
4596
4623
|
this.rebuildIfNeeded();
|
|
4597
4624
|
const pivot = this.pivot;
|
|
4625
|
+
this.writeAnimationUniforms();
|
|
4598
4626
|
if (this.isShaderField) {
|
|
4599
4627
|
pivot.matrix.identity();
|
|
4600
4628
|
const u = this.bladesMaterial.uniforms;
|
|
4601
|
-
if (u.time) u.time.value = this.time;
|
|
4602
|
-
if (u.windStrength) u.windStrength.value = this.sway * (this.isMesh ? MESH_SWAY_TO_WIND : SWAY_TO_WIND);
|
|
4603
4629
|
(u.bottomColor?.value).set(this.colorA);
|
|
4604
4630
|
(u.topColor?.value).set(this.colorB);
|
|
4605
4631
|
if (this.isMesh) {
|
|
@@ -4608,17 +4634,8 @@ var Foliage3D = class Foliage3D extends Node3D {
|
|
|
4608
4634
|
if (u.fadeStart) u.fadeStart.value = this.fadeStart;
|
|
4609
4635
|
if (u.fadeEnd) u.fadeEnd.value = this.fadeEnd;
|
|
4610
4636
|
}
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
const b = this.pickedBenders[i];
|
|
4614
|
-
if (b) slots[i]?.set(b.x, b.y, b.z, b.radius);
|
|
4615
|
-
else slots[i]?.set(0, 0, 0, 0);
|
|
4616
|
-
}
|
|
4617
|
-
} else if (this.isTufts) {
|
|
4618
|
-
pivot.matrix.identity();
|
|
4619
|
-
if (this.tuftTime) this.tuftTime.value = this.time;
|
|
4620
|
-
if (this.tuftStrength) this.tuftStrength.value = this.sway * TUFT_SWAY_TO_WIND;
|
|
4621
|
-
} else if (this.sway > 0) {
|
|
4637
|
+
} else if (this.isTufts) pivot.matrix.identity();
|
|
4638
|
+
else if (this.sway > 0) {
|
|
4622
4639
|
const leanX = Math.sin(this.time * 1.7) * SWAY_LEAN * this.sway;
|
|
4623
4640
|
const leanZ = Math.sin(this.time * 1.3 + 1.7) * SWAY_LEAN * this.sway * .6;
|
|
4624
4641
|
pivot.matrix.makeShear(0, 0, leanX, leanZ, 0, 0);
|
|
@@ -4645,7 +4662,7 @@ var Foliage3D = class Foliage3D extends Node3D {
|
|
|
4645
4662
|
computeBenders() {
|
|
4646
4663
|
if (!this.interaction || !this.isShaderField) return [];
|
|
4647
4664
|
const [fx, fy, fz] = worldXZY(this);
|
|
4648
|
-
if (this.drape && !this.drapeTerrain) this.resolveDrape();
|
|
4665
|
+
if (this.drape === true && !this.drapeTerrain) this.resolveDrape();
|
|
4649
4666
|
const terrain = this.drapeTerrain;
|
|
4650
4667
|
const candidates = [];
|
|
4651
4668
|
for (const b of movingBodiesFor(this)) {
|
|
@@ -4706,7 +4723,7 @@ var Foliage3D = class Foliage3D extends Node3D {
|
|
|
4706
4723
|
/** Resolve the drape target + cache the field's world position for `bedY`. */
|
|
4707
4724
|
resolveDrape() {
|
|
4708
4725
|
this.drapeTerrain = null;
|
|
4709
|
-
if (
|
|
4726
|
+
if (this.drape === false) return;
|
|
4710
4727
|
const terrain = findDrapeTerrain(this, this.terrain);
|
|
4711
4728
|
if (terrain) {
|
|
4712
4729
|
this.drapeTerrain = terrain;
|
|
@@ -8411,7 +8428,7 @@ var Tree3D = class Tree3D extends Node3D {
|
|
|
8411
8428
|
leafFadeStart: { default: 0 },
|
|
8412
8429
|
leafFadeEnd: { default: 0 },
|
|
8413
8430
|
leafShadows: { default: true },
|
|
8414
|
-
drape: { default:
|
|
8431
|
+
drape: { default: null },
|
|
8415
8432
|
terrain: { default: "" }
|
|
8416
8433
|
};
|
|
8417
8434
|
/** 'simple' (primitive low-poly) | 'medium' (light ez-trees) | 'high' (full). */
|
|
@@ -8440,11 +8457,14 @@ var Tree3D = class Tree3D extends Node3D {
|
|
|
8440
8457
|
/** Let leaves cast shadows. false keeps trunk/branch shadows but drops the
|
|
8441
8458
|
* expensive alpha-cutout leaf shadow pass (the dappled floor) for big FPS. */
|
|
8442
8459
|
leafShadows = true;
|
|
8443
|
-
/**
|
|
8444
|
-
*
|
|
8445
|
-
*
|
|
8446
|
-
*
|
|
8447
|
-
|
|
8460
|
+
/**
|
|
8461
|
+
* Drape the grove over a Terrain3D: each scattered instance roots at the
|
|
8462
|
+
* ground height under it (not the node's single Y), so a patch on rolling
|
|
8463
|
+
* or carved terrain never floats/buries. null (the default) is AUTO:
|
|
8464
|
+
* whenever the scene has a Terrain3D the grove drapes onto it. true forces
|
|
8465
|
+
* it (keeps retrying until a terrain appears), false disables draping.
|
|
8466
|
+
*/
|
|
8467
|
+
drape = null;
|
|
8448
8468
|
/** Node path to the Terrain3D to drape onto ('' = auto-find the first one). */
|
|
8449
8469
|
terrain = "";
|
|
8450
8470
|
/** Resolved drape target + the grove's world position, set per rebuild. */
|
|
@@ -8463,7 +8483,7 @@ var Tree3D = class Tree3D extends Node3D {
|
|
|
8463
8483
|
if (!((t.area[0] ?? 0) > 0) || !((t.area[1] ?? 0) > 0)) throw new IncantoError("BAD_FORMAT", `Tree3D '${node.name}' area must be positive [x, z] meters, got ${JSON.stringify(t.area)}.`, { prop: "area" });
|
|
8464
8484
|
if (t.leafFadeEnd !== 0 && !(t.leafFadeEnd > t.leafFadeStart && t.leafFadeStart >= 0)) throw new IncantoError("BAD_FORMAT", `Tree3D '${node.name}' needs leafFadeEnd > leafFadeStart >= 0 (the leaf LOD window) or 0/0 to disable, got start ${t.leafFadeStart}, end ${t.leafFadeEnd}.`, { prop: "leafFadeStart" });
|
|
8465
8485
|
if (typeof t.leafShadows !== "boolean") throw new IncantoError("BAD_FORMAT", `Tree3D '${node.name}' leafShadows must be a boolean, got ${JSON.stringify(t.leafShadows)}.`, { prop: "leafShadows" });
|
|
8466
|
-
if (typeof t.drape !== "boolean") throw new IncantoError("BAD_FORMAT", `Tree3D '${node.name}' drape must be a
|
|
8486
|
+
if (t.drape !== null && typeof t.drape !== "boolean") throw new IncantoError("BAD_FORMAT", `Tree3D '${node.name}' drape must be true, false or null (null = auto: drape whenever the scene has a Terrain3D), got ${JSON.stringify(t.drape)}.`, { prop: "drape" });
|
|
8467
8487
|
if (typeof t.terrain !== "string") throw new IncantoError("BAD_FORMAT", `Tree3D '${node.name}' terrain must be a node-path string (empty = auto-find), got ${JSON.stringify(t.terrain)}.`, { prop: "terrain" });
|
|
8468
8488
|
if (t.tier === "simple") return;
|
|
8469
8489
|
const perTree = maxVariantTriangles(t.tier, t.type);
|
|
@@ -8540,7 +8560,7 @@ var Tree3D = class Tree3D extends Node3D {
|
|
|
8540
8560
|
/** Resolve the drape target + cache the grove's world position for `bedY`. */
|
|
8541
8561
|
resolveDrape() {
|
|
8542
8562
|
this.drapeTerrain = null;
|
|
8543
|
-
if (
|
|
8563
|
+
if (this.drape === false) return;
|
|
8544
8564
|
const terrain = findDrapeTerrain(this, this.terrain);
|
|
8545
8565
|
if (terrain) {
|
|
8546
8566
|
this.drapeTerrain = terrain;
|
|
@@ -10324,6 +10344,11 @@ uniform vec3 uScale;
|
|
|
10324
10344
|
// incanto: world-anchor + interaction ripples (x, z, age, amplitude)
|
|
10325
10345
|
uniform vec3 uWaterCenter;
|
|
10326
10346
|
uniform vec4 uRipples[8];
|
|
10347
|
+
// incanto swell: directional traveling wave trains (0 = off — legacy look).
|
|
10348
|
+
// uSwellDir is a unit XZ vector; amplitude in meters; wavelength in meters.
|
|
10349
|
+
uniform float uSwellAmplitude;
|
|
10350
|
+
uniform vec2 uSwellDir;
|
|
10351
|
+
uniform float uSwellWavelength;
|
|
10327
10352
|
|
|
10328
10353
|
varying vec3 vNormal;
|
|
10329
10354
|
varying vec3 vWorldPosition;
|
|
@@ -10406,10 +10431,34 @@ float getRippleHeight(vec2 p) {
|
|
|
10406
10431
|
return h;
|
|
10407
10432
|
}
|
|
10408
10433
|
|
|
10409
|
-
// incanto:
|
|
10410
|
-
//
|
|
10434
|
+
// incanto swell: one peaked traveling wave train. Deep-water dispersion
|
|
10435
|
+
// (c = sqrt(g/k)) gives each wavelength its REAL speed, so short chop
|
|
10436
|
+
// overtakes long swell exactly like the open sea. The pow-shaped profile
|
|
10437
|
+
// sharpens crests and flattens troughs (a height-only Gerstner stand-in —
|
|
10438
|
+
// no XZ pinch, so the analytic finite-difference normals stay exact).
|
|
10439
|
+
float swellWave(vec2 p, vec2 dir, float lambda, float amp, float sharp) {
|
|
10440
|
+
float k = 6.2831853 / max(lambda, 1.0);
|
|
10441
|
+
float c = sqrt(9.8 / k);
|
|
10442
|
+
float s = 0.5 + 0.5 * sin(dot(p, dir) * k - uTime * c * k);
|
|
10443
|
+
return amp * (pow(s, sharp) * 2.0 - 1.0);
|
|
10444
|
+
}
|
|
10445
|
+
|
|
10446
|
+
// incanto swell: three trains — the primary + two shorter crossing sets
|
|
10447
|
+
// (+25° / −19°) so crest lines stay broken and organic, never a zebra field.
|
|
10448
|
+
float getSwell(vec2 p) {
|
|
10449
|
+
if (uSwellAmplitude <= 0.0) return 0.0;
|
|
10450
|
+
vec2 d1 = uSwellDir;
|
|
10451
|
+
vec2 d2 = normalize(vec2(d1.x * 0.906 - d1.y * 0.423, d1.x * 0.423 + d1.y * 0.906));
|
|
10452
|
+
vec2 d3 = normalize(vec2(d1.x * 0.946 + d1.y * 0.326, -d1.x * 0.326 + d1.y * 0.946));
|
|
10453
|
+
return swellWave(p, d1, uSwellWavelength, uSwellAmplitude * 0.60, 2.6)
|
|
10454
|
+
+ swellWave(p, d2, uSwellWavelength * 0.53, uSwellAmplitude * 0.27, 2.2)
|
|
10455
|
+
+ swellWave(p, d3, uSwellWavelength * 0.31, uSwellAmplitude * 0.16, 1.8);
|
|
10456
|
+
}
|
|
10457
|
+
|
|
10458
|
+
// incanto: waves + swell + ripples — used for displacement AND the normal
|
|
10459
|
+
// samples so every layer catches the light like real waves.
|
|
10411
10460
|
float getHeight(float x, float z) {
|
|
10412
|
-
return getElevation(x, z) + getRippleHeight(vec2(x, z));
|
|
10461
|
+
return getElevation(x, z) + getSwell(vec2(x, z)) + getRippleHeight(vec2(x, z));
|
|
10413
10462
|
}
|
|
10414
10463
|
|
|
10415
10464
|
void main() {
|
|
@@ -10518,6 +10567,15 @@ uniform vec4 uRipples[8];
|
|
|
10518
10567
|
uniform float uRippleFoam[8];
|
|
10519
10568
|
uniform float uSplashFoam;
|
|
10520
10569
|
|
|
10570
|
+
// incanto swell: open-water WHITECAPS — foam breaking on the highest crests,
|
|
10571
|
+
// independent of the shoreline depth mask. uWaveEnvelope is the JS-computed
|
|
10572
|
+
// total wave amplitude (FBM + swell) so the crest mask normalizes by the
|
|
10573
|
+
// actual sea state, not the surface's extent. uSwellAmplitude gates the
|
|
10574
|
+
// swell-only color work (crest banding + wave-face shading).
|
|
10575
|
+
uniform float uWhitecaps;
|
|
10576
|
+
uniform float uWaveEnvelope;
|
|
10577
|
+
uniform float uSwellAmplitude;
|
|
10578
|
+
|
|
10521
10579
|
// 🎨 Contact surface color customization uniforms
|
|
10522
10580
|
uniform vec3 uEdgeColor;
|
|
10523
10581
|
uniform float uEdgeIntensity;
|
|
@@ -10904,6 +10962,24 @@ void main() {
|
|
|
10904
10962
|
// Mix between surface and peak colors based on peak transition
|
|
10905
10963
|
vec3 mixedColor2 = mix(mixedColor1, uPeakColor, peakFactor);
|
|
10906
10964
|
|
|
10965
|
+
// incanto swell: the legacy ramp normalizes elevation by the surface's
|
|
10966
|
+
// HALF-EXTENT — on a real ocean plane that's hundreds of meters, so the
|
|
10967
|
+
// ramp never sees a wave. When swell is on, re-read the crest height
|
|
10968
|
+
// against the actual sea state (uWaveEnvelope) and (a) lighten crest tops
|
|
10969
|
+
// toward the peak color, (b) shade the wave FACES with a gentle N·L off
|
|
10970
|
+
// the distance-smoothed geometry normal — the lit/shadow lanes are what
|
|
10971
|
+
// make open-ocean swell READ at any distance. Both gated: swell 0 keeps
|
|
10972
|
+
// the legacy look byte-identical.
|
|
10973
|
+
if (uSwellAmplitude > 0.0) {
|
|
10974
|
+
float crestBand = smoothstep(0.3, 0.9,
|
|
10975
|
+
(vWorldPosition.y - uWaterCenter.y) / max(uWaveEnvelope, 0.001));
|
|
10976
|
+
mixedColor2 = mix(mixedColor2, uPeakColor, crestBand * 0.45);
|
|
10977
|
+
float faceShade = clamp(dot(normalize(mix(vec3(0.0, 1.0, 0.0), normalize(vNormal),
|
|
10978
|
+
1.0 - 0.9 * smoothstep(150.0, 600.0, length(vWorldPosition - cameraPosition)))),
|
|
10979
|
+
normalize(uSunDirection)), 0.0, 1.0);
|
|
10980
|
+
mixedColor2 *= 0.80 + 0.32 * faceShade;
|
|
10981
|
+
}
|
|
10982
|
+
|
|
10907
10983
|
// incanto v2: Beer's-law depth absorption + screen-space refraction.
|
|
10908
10984
|
// Shallow water transmits the (refracted) scene almost untouched; depth
|
|
10909
10985
|
// exponentially absorbs it into the ramp color — clear turquoise edges,
|
|
@@ -11040,6 +11116,22 @@ void main() {
|
|
|
11040
11116
|
if (uEnableFoam > 0.5) {
|
|
11041
11117
|
foamAmount = calculateFoam();
|
|
11042
11118
|
}
|
|
11119
|
+
// incanto swell: whitecaps — foam eats the TOPS of the tallest crests in
|
|
11120
|
+
// open water. The crest mask normalizes elevation by the real wave envelope
|
|
11121
|
+
// (uScale.y is the surface's half-extent — useless as a sea-state yardstick
|
|
11122
|
+
// on a big ocean plane), and a two-octave noise breaks the caps into
|
|
11123
|
+
// patches that live and die with the crests. Distance-faded: far whitecaps
|
|
11124
|
+
// subtend under a pixel and would alias into horizon speckle.
|
|
11125
|
+
if (uWhitecaps > 0.0 && uWaveEnvelope > 0.001) {
|
|
11126
|
+
float crestN = (vWorldPosition.y - uWaterCenter.y) / uWaveEnvelope;
|
|
11127
|
+
float cap = smoothstep(0.5, 0.85, crestN);
|
|
11128
|
+
vec2 capUV = vWorldPosition.xz * 0.3;
|
|
11129
|
+
float capNoise = noise(capUV * 2.2 + uTime * vec2(0.10, 0.06)) * 0.65
|
|
11130
|
+
+ noise(capUV * 6.5 - uTime * vec2(0.05, 0.14)) * 0.35;
|
|
11131
|
+
float capFade = 1.0 - smoothstep(220.0, 640.0, camDist);
|
|
11132
|
+
float whitecap = uWhitecaps * cap * smoothstep(0.42, 0.78, capNoise) * capFade;
|
|
11133
|
+
foamAmount = max(foamAmount, whitecap);
|
|
11134
|
+
}
|
|
11043
11135
|
// incanto: splash/wake whitewater rides the ripple buffer, INDEPENDENT of the
|
|
11044
11136
|
// depth-foam gate so it works even on shallow ponds / before the first pre-pass
|
|
11045
11137
|
float splashFoam = rippleFoam(vWorldPosition.xz);
|
|
@@ -11449,7 +11541,11 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11449
11541
|
detailStrength: { default: .26 },
|
|
11450
11542
|
absorption: { default: .15 },
|
|
11451
11543
|
refraction: { default: true },
|
|
11452
|
-
underwater: { default: true }
|
|
11544
|
+
underwater: { default: true },
|
|
11545
|
+
swell: { default: 0 },
|
|
11546
|
+
swellDirectionDeg: { default: 0 },
|
|
11547
|
+
swellWavelength: { default: 30 },
|
|
11548
|
+
whitecaps: { default: 0 }
|
|
11453
11549
|
};
|
|
11454
11550
|
/** [width, depth] in meters (the surface lies on XZ). */
|
|
11455
11551
|
size = [40, 40];
|
|
@@ -11504,6 +11600,21 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11504
11600
|
* `{ color?, visibility? }` overrides the fog hue / view distance (meters).
|
|
11505
11601
|
*/
|
|
11506
11602
|
underwater = true;
|
|
11603
|
+
/**
|
|
11604
|
+
* Directional traveling SWELL amplitude in meters (fancy only; 0 = off, the
|
|
11605
|
+
* legacy isotropic look). Three peaked wave trains march across the surface
|
|
11606
|
+
* at real deep-water speeds — THE open-ocean dial: 0.15 = lively lake chop,
|
|
11607
|
+
* 0.4 = coastal sea, 0.8 = heavy weather. Crests feed the color ramp,
|
|
11608
|
+
* `whitecaps` and the shore foam automatically.
|
|
11609
|
+
*/
|
|
11610
|
+
swell = 0;
|
|
11611
|
+
/** Compass direction the swell TRAVELS toward, degrees (0 = +z, 90 = +x). */
|
|
11612
|
+
swellDirectionDeg = 0;
|
|
11613
|
+
/** Primary swell wavelength in meters (the two crossing trains derive). */
|
|
11614
|
+
swellWavelength = 30;
|
|
11615
|
+
/** Open-water whitecap foam on the tallest crests, 0–1 (fancy only). Works
|
|
11616
|
+
* best with `swell` — the caps ride the swell's crest lines. */
|
|
11617
|
+
whitecaps = 0;
|
|
11507
11618
|
/** Loader hook: degenerate planes and bad enums fail at LOAD, not at render. */
|
|
11508
11619
|
static validateJson(node) {
|
|
11509
11620
|
const w = node;
|
|
@@ -11525,6 +11636,9 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11525
11636
|
if (!(w.sunIntensity >= 0)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' sunIntensity must be >= 0, got ${w.sunIntensity}.`, { prop: "sunIntensity" });
|
|
11526
11637
|
if (!(w.detailStrength >= 0)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' detailStrength must be >= 0, got ${w.detailStrength}.`, { prop: "detailStrength" });
|
|
11527
11638
|
if (!(w.absorption >= 0)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' absorption must be >= 0 (per-meter Beer's-law constant), got ${w.absorption}.`, { prop: "absorption" });
|
|
11639
|
+
if (!(w.swell >= 0) || !Number.isFinite(w.swell)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' swell must be >= 0 meters (0 = off), got ${JSON.stringify(w.swell)}.`, { prop: "swell" });
|
|
11640
|
+
if (!(w.swellWavelength >= 2)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' swellWavelength must be >= 2 meters, got ${JSON.stringify(w.swellWavelength)}.`, { prop: "swellWavelength" });
|
|
11641
|
+
if (!(w.whitecaps >= 0) || !(w.whitecaps <= 1)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' whitecaps must be in [0, 1], got ${JSON.stringify(w.whitecaps)}.`, { prop: "whitecaps" });
|
|
11528
11642
|
const uw = w.underwater;
|
|
11529
11643
|
if (typeof uw !== "boolean") {
|
|
11530
11644
|
if (typeof uw !== "object" || uw === null || Array.isArray(uw)) throw new IncantoError("BAD_FORMAT", `Water3D '${node.name}' underwater must be true, false or an object ({ color?, visibility? }), got ${JSON.stringify(uw)}.`, { prop: "underwater" });
|
|
@@ -11778,7 +11892,12 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11778
11892
|
uCameraFar: { value: 1e3 },
|
|
11779
11893
|
uEdgeColor: { value: new Color(FOAM_LOOK.edgeColor) },
|
|
11780
11894
|
uEdgeIntensity: { value: FOAM_LOOK.edgeIntensity },
|
|
11781
|
-
uEdgeWidth: { value: FOAM_LOOK.edgeWidth }
|
|
11895
|
+
uEdgeWidth: { value: FOAM_LOOK.edgeWidth },
|
|
11896
|
+
uSwellAmplitude: { value: this.swell },
|
|
11897
|
+
uSwellDir: { value: new Vector2(0, 1) },
|
|
11898
|
+
uSwellWavelength: { value: this.swellWavelength },
|
|
11899
|
+
uWhitecaps: { value: this.whitecaps },
|
|
11900
|
+
uWaveEnvelope: { value: 0 }
|
|
11782
11901
|
},
|
|
11783
11902
|
transparent: true,
|
|
11784
11903
|
depthTest: true,
|
|
@@ -11840,6 +11959,12 @@ var Water3D = class Water3D extends Node3D {
|
|
|
11840
11959
|
if (u.uSunIntensity) u.uSunIntensity.value = this.sunIntensity;
|
|
11841
11960
|
if (u.uDetailStrength) u.uDetailStrength.value = this.detailStrength;
|
|
11842
11961
|
if (u.uAbsorption) u.uAbsorption.value = this.absorption;
|
|
11962
|
+
if (u.uSwellAmplitude) u.uSwellAmplitude.value = this.swell;
|
|
11963
|
+
if (u.uSwellWavelength) u.uSwellWavelength.value = this.swellWavelength;
|
|
11964
|
+
if (u.uWhitecaps) u.uWhitecaps.value = this.whitecaps;
|
|
11965
|
+
const swellRad = this.swellDirectionDeg * Math.PI / 180;
|
|
11966
|
+
(u.uSwellDir?.value)?.set(Math.sin(swellRad), Math.cos(swellRad));
|
|
11967
|
+
if (u.uWaveEnvelope) u.uWaveEnvelope.value = this.waveHeight * AMPLITUDE_PER_WAVE_HEIGHT * 1.5 + this.swell * 1.03;
|
|
11843
11968
|
if (!this.reflection && u.uUseEnvironmentMap) u.uUseEnvironmentMap.value = 0;
|
|
11844
11969
|
if (!this.foam && u.uEnableFoam) u.uEnableFoam.value = 0;
|
|
11845
11970
|
if (!this.refraction && u.uUseRefraction) u.uUseRefraction.value = 0;
|
package/dist/test.js
CHANGED
|
@@ -6,7 +6,7 @@ import { n as jsonEquals, t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
|
6
6
|
import { i as getNodeSchema, s as mergeStaticProps } from "./registry-BVJ2HbCn.js";
|
|
7
7
|
import { n as registerGameplayBehaviors } from "./gameplay-sSqrUcnz.js";
|
|
8
8
|
import { t as registerNodes2D } from "./register-Djwckzgx.js";
|
|
9
|
-
import { t as registerNodes3D } from "./register-
|
|
9
|
+
import { t as registerNodes3D } from "./register-Bh_3Z39N.js";
|
|
10
10
|
import { t as registerNodesNet } from "./register-BFFE1Mh1.js";
|
|
11
11
|
//#region src/test/index.ts
|
|
12
12
|
/**
|
|
@@ -127,7 +127,7 @@ async function runScript(json, opts) {
|
|
|
127
127
|
const { enablePhysics2D } = await import("./physics-2d-BiIdl51r.js").then((n) => n.r);
|
|
128
128
|
await enablePhysics2D(engine);
|
|
129
129
|
} else if (physics === "3d" || physics === "auto" && scene.dimension === "3d") {
|
|
130
|
-
const { enablePhysics3D } = await import("./physics-3d-
|
|
130
|
+
const { enablePhysics3D } = await import("./physics-3d-TmOuCy7J.js").then((n) => n.r);
|
|
131
131
|
await enablePhysics3D(engine);
|
|
132
132
|
}
|
|
133
133
|
const failures = [];
|
|
@@ -232,7 +232,7 @@ async function createPlaySession(json, opts = {}) {
|
|
|
232
232
|
const { enablePhysics2D } = await import("./physics-2d-BiIdl51r.js").then((n) => n.r);
|
|
233
233
|
await enablePhysics2D(engine);
|
|
234
234
|
} else if (physics === "3d" || physics === "auto" && scene.dimension === "3d") {
|
|
235
|
-
const { enablePhysics3D } = await import("./physics-3d-
|
|
235
|
+
const { enablePhysics3D } = await import("./physics-3d-TmOuCy7J.js").then((n) => n.r);
|
|
236
236
|
await enablePhysics3D(engine);
|
|
237
237
|
}
|
|
238
238
|
const stepMs = 1e3 / (opts.fixedHz ?? 60);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./index-
|
|
1
|
+
import{t as e}from"./index-CofH0yGY.js";async function t(t){return new n((await e(()=>import(`./GameServer-C56iOUgF.js`),[],import.meta.url)).GameServer,t)}var n=class{raw;active=new Map;reconnecting=!1;disposed=!1;constructor(e,t){this.raw=new e({...t})}get account(){return this.raw.account}get connected(){return this.raw.connected}connect(){return this.raw.connected?Promise.resolve(!0):(this.disposed=!1,this.rawConnect())}rawConnect(){return this.raw.connect({onDisconnect:()=>void this.reconnect()})}disconnect(){this.disposed=!0;for(let e of this.active.values())e.off();return this.active.clear(),this.raw.disconnect()}remoteFunction(e,t,n){return this.raw.remoteFunction(e,t,n)}track(e){let t=Symbol(`sub`),n={make:e,off:e()};return this.active.set(t,n),()=>{n.off(),this.active.delete(t)}}async reconnect(){if(!this.disposed&&!this.reconnecting){this.reconnecting=!0;try{await this.rawConnect();for(let e of this.active.values())e.off(),e.off=e.make()}finally{this.reconnecting=!1}}}subscribeRoomState(e,t){return this.track(()=>this.raw.subscribeRoomState(e,t))}subscribeRoomMyState(e,t){return this.track(()=>this.raw.subscribeRoomMyState(e,t))}subscribeRoomAllUserStates(e,t){return this.track(()=>this.raw.subscribeRoomAllUserStates(e,e=>{let n={};for(let t of e??[]){if(!t||typeof t.account!=`string`||t.__leaved)continue;let{account:e,__updated:r,__leaved:i,...a}=t;n[e]=a}t(n)}))}subscribeRoomCollection(e,t,n){return this.track(()=>this.raw.subscribeRoomCollection(e,t,({items:e})=>{let t={};for(let n of e??[])n&&typeof n.__id==`string`&&(t[n.__id]=n);n(t)}))}onRoomMessage(e,t,n){return this.track(()=>this.raw.onRoomMessage(e,t,n))}onRoomUserJoin(e,t){return this.track(()=>this.raw.onRoomUserJoin(e,t))}onRoomUserLeave(e,t){return this.track(()=>this.raw.onRoomUserLeave(e,t))}subscribeGlobalState(e){return this.track(()=>this.raw.subscribeGlobalState(e))}subscribeGlobalMyState(e){return this.track(()=>this.raw.subscribeGlobalMyState(e))}subscribeGlobalUserState(e,t){return this.track(()=>this.raw.subscribeGlobalUserState(e,t))}subscribeGlobalCollection(e,t){return this.track(()=>this.raw.subscribeGlobalCollection(e,({items:e})=>{let n={};for(let t of e??[])t&&typeof t.__id==`string`&&(n[t.__id]=t);t(n)}))}subscribeAsset(e,t){return this.track(()=>this.raw.subscribeAsset(e,t))}onGlobalMessage(e,t){return this.track(()=>this.raw.onGlobalMessage(e,t))}};export{t as createAgent8Server};
|