incanto 0.10.0 → 0.12.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/2d.js +2 -2
- package/dist/3d.d.ts +68 -2
- package/dist/3d.js +73 -4
- package/dist/{create-game-Cq0Z41EQ.js → create-game-B2fewJUy.js} +72 -21
- package/dist/{create-game-CdWhP6ve.js → create-game-C_xf4gm9.js} +1 -1
- package/dist/index.d.ts +1 -28
- package/dist/index.js +1 -1
- package/dist/{audio-player-Dyjg5k92.d.ts → pathfinding-BSiXjd6W.d.ts} +28 -1
- package/dist/{physics-2d-DweTURFt.js → physics-2d-B6D864oZ.js} +6 -2
- package/dist/{physics-3d-D8m2Hd-q.js → physics-3d-RLNaxRyw.js} +39 -3
- package/dist/react.js +1 -1
- package/dist/{register-BP-kbijm.js → register-ysLR3WQS.js} +5 -1
- package/dist/test.js +5 -5
- package/editor/assets/{agent8--Cd_2Y95.js → agent8-D_4QY8Aq.js} +1 -1
- package/editor/assets/index-s0DZuroe.js +7429 -0
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/skills/incanto-3d-character.md +10 -4
- package/skills/incanto-building-3d-games.md +35 -0
- package/skills/incanto-editor.md +3 -3
- package/skills/incanto-physics-and-input.md +8 -0
- package/editor/assets/index-Dp_cYQx1.js +0 -7417
package/dist/2d.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
2
|
-
import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-
|
|
2
|
+
import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-C_xf4gm9.js";
|
|
3
3
|
import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-BD6zgrv_.js";
|
|
4
|
-
import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-
|
|
4
|
+
import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-B6D864oZ.js";
|
|
5
5
|
//#region src/2d/library-sprite.ts
|
|
6
6
|
/**
|
|
7
7
|
* Turn a library sprite-animation JSON into a scene-ready spritesheet asset
|
package/dist/3d.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { s as JsonObject } from "./schema-CcoWb32N.js";
|
|
|
2
2
|
import { $ as Node, C as RendererStats, S as GameStats, b as Scheduler, l as PropSchema, n as BehaviorCtor, v as Engine, w as Scene$1 } from "./behavior-Bod1AyJS.js";
|
|
3
3
|
import { t as LoadSceneOptions } from "./loader-BcUDfNHn.js";
|
|
4
4
|
import { t as ParticleSim } from "./particle-sim-CwJ5rI_P.js";
|
|
5
|
-
import {
|
|
5
|
+
import { n as PathGrid, s as SpatialPose } from "./pathfinding-BSiXjd6W.js";
|
|
6
6
|
import { AnimationClip, BufferGeometry, Color, DirectionalLight, InstancedMesh, MeshPhysicalMaterial, Object3D, PerspectiveCamera, Scene, Vector3, WebGLRenderer } from "three";
|
|
7
7
|
import { VRM } from "@pixiv/three-vrm";
|
|
8
8
|
import { Sky } from "three/examples/jsm/objects/Sky.js";
|
|
@@ -311,6 +311,20 @@ declare class Physics3D {
|
|
|
311
311
|
normal: [number, number, number];
|
|
312
312
|
node: PhysicsBody3D | null;
|
|
313
313
|
} | null;
|
|
314
|
+
/**
|
|
315
|
+
* Sweep a sphere of `radius` from `origin` along `dir` — a THICK ray. The
|
|
316
|
+
* spring-arm camera probe uses this instead of `castRay`: a thin ray that
|
|
317
|
+
* skims 10 cm over a wall reports "clear" while the camera's near plane
|
|
318
|
+
* still clips the wall; the ball's radius covers that band. Same filters
|
|
319
|
+
* as `castRay` (sensors never hit; `staticOnly` ignores dynamic/kinematic).
|
|
320
|
+
* Returns the travel distance of the sphere CENTER, or null when clear.
|
|
321
|
+
*/
|
|
322
|
+
castSphere(origin: [number, number, number], dir: [number, number, number], radius: number, maxLen: number, exclude?: PhysicsBody3D, opts?: {
|
|
323
|
+
staticOnly?: boolean;
|
|
324
|
+
}): {
|
|
325
|
+
distance: number;
|
|
326
|
+
node: PhysicsBody3D | null;
|
|
327
|
+
} | null;
|
|
314
328
|
}
|
|
315
329
|
//#endregion
|
|
316
330
|
//#region src/3d/create-game.d.ts
|
|
@@ -460,6 +474,14 @@ interface BloomEnvironment {
|
|
|
460
474
|
/** How strongly the blurred glow is added back (0 = off, ~1.2 = neon). */
|
|
461
475
|
strength: number;
|
|
462
476
|
}
|
|
477
|
+
interface PostEnvironment {
|
|
478
|
+
/** Corner darkening, 0 (off) … 1 (heavy). Default 0. */
|
|
479
|
+
vignette: number;
|
|
480
|
+
/** Color saturation multiplier: 0 = grayscale, 1 = neutral. Default 1. */
|
|
481
|
+
saturation: number;
|
|
482
|
+
/** Contrast around mid-gray: 1 = neutral. Default 1. */
|
|
483
|
+
contrast: number;
|
|
484
|
+
}
|
|
463
485
|
interface Environment3DConfig {
|
|
464
486
|
/** Tone-mapping exposure (ACES), default 1. */
|
|
465
487
|
exposure: number;
|
|
@@ -471,6 +493,8 @@ interface Environment3DConfig {
|
|
|
471
493
|
clouds: CloudsEnvironment | null;
|
|
472
494
|
/** Bloom post pass (bright-pass → blur → additive composite), or null. */
|
|
473
495
|
bloom: BloomEnvironment | null;
|
|
496
|
+
/** Color grade + vignette (tone-mapped composite tail), or null. */
|
|
497
|
+
post: PostEnvironment | null;
|
|
474
498
|
/**
|
|
475
499
|
* `null` = not declared (shadow maps stay available, free until a light
|
|
476
500
|
* casts), `false` = force-disabled, object = declared ON with quality knobs
|
|
@@ -553,6 +577,8 @@ declare class Environment3D {
|
|
|
553
577
|
get clouds(): CloudsEnvironment | null;
|
|
554
578
|
/** Parsed bloom config, or null when no bloom pass is declared. */
|
|
555
579
|
get bloom(): BloomEnvironment | null;
|
|
580
|
+
/** Parsed color-grade/vignette config, or null when not declared. */
|
|
581
|
+
get post(): PostEnvironment | null;
|
|
556
582
|
/** The live scene fog (color/near/far) the cloud composite fades into, or null. */
|
|
557
583
|
get sceneFog(): {
|
|
558
584
|
color: Color;
|
|
@@ -2193,4 +2219,44 @@ interface WalkState {
|
|
|
2193
2219
|
ignoreStatic: boolean;
|
|
2194
2220
|
}
|
|
2195
2221
|
//#endregion
|
|
2196
|
-
|
|
2222
|
+
//#region src/3d/terrain-nav.d.ts
|
|
2223
|
+
/**
|
|
2224
|
+
* Terrain navigation — the bridge from a `Terrain3D` heightfield to the grid
|
|
2225
|
+
* A* (`findPath`). Sample the surface into walkable cells (slope- and
|
|
2226
|
+
* height-limited), path on the grid, then lift waypoints back onto the
|
|
2227
|
+
* surface with `toWorld` (its y IS the terrain height):
|
|
2228
|
+
*
|
|
2229
|
+
* const nav = buildTerrainNav(terrain, { cellSize: 2, maxSlopeDeg: 40 });
|
|
2230
|
+
* const cells = findPath(nav.grid, nav.toCell(wolfX, wolfZ), nav.toCell(px, pz));
|
|
2231
|
+
* follow.setPath(cells.map(([cx, cy]) => nav.toWorld(cx, cy)));
|
|
2232
|
+
*
|
|
2233
|
+
* Trees/rocks/buildings aren't in the heightfield — stamp them out with
|
|
2234
|
+
* `setSolid(...nav.toCell(x, z))` after building.
|
|
2235
|
+
*/
|
|
2236
|
+
interface TerrainNav {
|
|
2237
|
+
/** Feed this straight into `findPath`. */
|
|
2238
|
+
grid: PathGrid;
|
|
2239
|
+
cellSize: number;
|
|
2240
|
+
/** World x/z → cell coords (unclamped — check bounds via grid width/height). */
|
|
2241
|
+
toCell(x: number, z: number): [number, number];
|
|
2242
|
+
/** Cell → world position AT THE SURFACE ([x, terrainHeight, z], cell center). */
|
|
2243
|
+
toWorld(cx: number, cy: number): [number, number, number];
|
|
2244
|
+
/** Mark a cell unwalkable (props, buildings, no-go zones). */
|
|
2245
|
+
setSolid(cx: number, cy: number): void;
|
|
2246
|
+
}
|
|
2247
|
+
/** What we need from the terrain — Terrain3D satisfies this. */
|
|
2248
|
+
interface HeightSampler extends Node {
|
|
2249
|
+
size: number[];
|
|
2250
|
+
heightAt(x: number, z: number): number;
|
|
2251
|
+
}
|
|
2252
|
+
interface TerrainNavOptions {
|
|
2253
|
+
/** Meters per cell (default 2 — character-scale corridors). */
|
|
2254
|
+
cellSize?: number;
|
|
2255
|
+
/** Steepest walkable slope, degrees (default 40). */
|
|
2256
|
+
maxSlopeDeg?: number;
|
|
2257
|
+
/** Cells whose surface is BELOW this world y are unwalkable (sea level). */
|
|
2258
|
+
minHeight?: number;
|
|
2259
|
+
}
|
|
2260
|
+
declare function buildTerrainNav(terrain: HeightSampler, opts?: TerrainNavOptions): TerrainNav;
|
|
2261
|
+
//#endregion
|
|
2262
|
+
export { Area3D, AssetStore3D, Billboard3D, type BillboardGroupMode, BoneAttachment3D, Camera3D, CharacterBody3D, CharacterController3D, type CreateGame3DOptions, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, Environment3D, type Environment3DConfig, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, type FlowerVariety, Flowers3D, type FogEnvironment, Foliage3D, type FoliageKind, type FoliageStyle, type Game3D, type HeightSampler, type Heightmap, type HeightmapOptions, Joint3D, type JointType3D, LoftMesh3D, type LoftSection, MeshInstance3D, type MeshKind, type MeshMaterialProps, type ModelEntry, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, type Physics3DOptions, PhysicsBody3D, QUARTER_PITCH, type RenderContext3D, type RenderHook3D, Renderer3D, type Renderer3DOptions, type RigView, RigidBody3D, type Ripple, type ShadowsEnvironment, type SkyEnvironment, StaticBody3D, type SunConsumer3D, type SyncOptions, type SyncResult, TERRAIN_THEMES, Terrain3D, type TerrainLayer, type TerrainNav, type TerrainNavOptions, type TerrainTheme, Trail3D, Tree3D, type TreeTier, type TreeType, VOXEL_PALETTE, type VoxelBlock, VoxelGrid3D, WATER_MAX_RIPPLES, Water3D, buildHeightmap, buildTerrainNav, cameraRelative, createGame3D, enablePhysics3D, horizonColorFromSky, keyboardIntensity, movementState, parseEnvironment3D, registerNodes3D, resolveFlowerDensity, rigPose, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers };
|
package/dist/3d.js
CHANGED
|
@@ -1,5 +1,74 @@
|
|
|
1
|
-
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-
|
|
2
|
-
import { A as PhysicsBody3D, C as Terrain3D, D as Joint3D, E as terrainThemeLayers, F as QUARTER_PITCH, I as cameraRelative, L as keyboardIntensity, M as StaticBody3D, N as Node3D, O as Area3D, R as movementState, S as Billboard3D, T as TERRAIN_THEMES, _ as resolveFlowerDensity, a as VoxelGrid3D, b as Camera3D, c as Particles3D, d as MeshInstance3D, f as DirectionalLight3D, g as Flowers3D, h as DENSITY_PRESETS, i as VOXEL_PALETTE, j as RigidBody3D, k as CharacterBody3D, l as ModelInstance3D, m as Foliage3D, n as Water3D, o as Tree3D, p as OmniLight3D, r as WATER_MAX_RIPPLES, s as Trail3D, t as registerNodes3D, u as LoftMesh3D, v as FLOWER_VARIETIES, w as DEFAULT_TERRAIN_TEXTURE_BASE, x as BoneAttachment3D, y as CharacterController3D, z as rigPose } from "./register-
|
|
1
|
+
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-B2fewJUy.js";
|
|
2
|
+
import { A as PhysicsBody3D, C as Terrain3D, D as Joint3D, E as terrainThemeLayers, F as QUARTER_PITCH, I as cameraRelative, L as keyboardIntensity, M as StaticBody3D, N as Node3D, O as Area3D, R as movementState, S as Billboard3D, T as TERRAIN_THEMES, _ as resolveFlowerDensity, a as VoxelGrid3D, b as Camera3D, c as Particles3D, d as MeshInstance3D, f as DirectionalLight3D, g as Flowers3D, h as DENSITY_PRESETS, i as VOXEL_PALETTE, j as RigidBody3D, k as CharacterBody3D, l as ModelInstance3D, m as Foliage3D, n as Water3D, o as Tree3D, p as OmniLight3D, r as WATER_MAX_RIPPLES, s as Trail3D, t as registerNodes3D, u as LoftMesh3D, v as FLOWER_VARIETIES, w as DEFAULT_TERRAIN_TEXTURE_BASE, x as BoneAttachment3D, y as CharacterController3D, z as rigPose } from "./register-ysLR3WQS.js";
|
|
3
3
|
import { n as splatWeights, t as buildHeightmap } from "./heightmap-CroQPEER.js";
|
|
4
|
-
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-
|
|
5
|
-
|
|
4
|
+
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-RLNaxRyw.js";
|
|
5
|
+
//#region src/3d/terrain-nav.ts
|
|
6
|
+
function buildTerrainNav(terrain, opts) {
|
|
7
|
+
const cellSize = opts?.cellSize ?? 2;
|
|
8
|
+
const maxSlopeDeg = opts?.maxSlopeDeg ?? 40;
|
|
9
|
+
const minHeight = opts?.minHeight ?? Number.NEGATIVE_INFINITY;
|
|
10
|
+
let ox = 0;
|
|
11
|
+
let oz = 0;
|
|
12
|
+
for (let n = terrain; n; n = n.parent) if (n instanceof Node3D) {
|
|
13
|
+
ox += n.position[0] ?? 0;
|
|
14
|
+
oz += n.position[2] ?? 0;
|
|
15
|
+
}
|
|
16
|
+
const sizeX = terrain.size[0] ?? 200;
|
|
17
|
+
const sizeZ = terrain.size[1] ?? 200;
|
|
18
|
+
const width = Math.max(1, Math.round(sizeX / cellSize));
|
|
19
|
+
const height = Math.max(1, Math.round(sizeZ / cellSize));
|
|
20
|
+
const minX = ox - sizeX / 2;
|
|
21
|
+
const minZ = oz - sizeZ / 2;
|
|
22
|
+
const centerX = (cx) => minX + (cx + .5) * cellSize;
|
|
23
|
+
const centerZ = (cy) => minZ + (cy + .5) * cellSize;
|
|
24
|
+
const tanLimit = Math.tan(maxSlopeDeg * Math.PI / 180);
|
|
25
|
+
const halfDiag = cellSize / 2 * Math.SQRT2;
|
|
26
|
+
const solidBits = new Uint8Array(width * height);
|
|
27
|
+
for (let cy = 0; cy < height; cy++) for (let cx = 0; cx < width; cx++) {
|
|
28
|
+
const i = cy * width + cx;
|
|
29
|
+
const x = centerX(cx);
|
|
30
|
+
const z = centerZ(cy);
|
|
31
|
+
const h = terrain.heightAt(x, z);
|
|
32
|
+
if (h < minHeight) {
|
|
33
|
+
solidBits[i] = 1;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const half = cellSize / 2;
|
|
37
|
+
for (const [dx, dz] of CORNERS) {
|
|
38
|
+
const hc = terrain.heightAt(x + dx * half, z + dz * half);
|
|
39
|
+
if (Math.abs(hc - h) / halfDiag > tanLimit) {
|
|
40
|
+
solidBits[i] = 1;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
grid: {
|
|
47
|
+
width,
|
|
48
|
+
height,
|
|
49
|
+
solid: (x, y) => x < 0 || y < 0 || x >= width || y >= height || solidBits[y * width + x] === 1
|
|
50
|
+
},
|
|
51
|
+
cellSize,
|
|
52
|
+
toCell: (x, z) => [Math.floor((x - minX) / cellSize), Math.floor((z - minZ) / cellSize)],
|
|
53
|
+
toWorld: (cx, cy) => {
|
|
54
|
+
const x = centerX(cx);
|
|
55
|
+
const z = centerZ(cy);
|
|
56
|
+
return [
|
|
57
|
+
x,
|
|
58
|
+
terrain.heightAt(x, z),
|
|
59
|
+
z
|
|
60
|
+
];
|
|
61
|
+
},
|
|
62
|
+
setSolid: (cx, cy) => {
|
|
63
|
+
if (cx >= 0 && cy >= 0 && cx < width && cy < height) solidBits[cy * width + cx] = 1;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const CORNERS = [
|
|
68
|
+
[1, 1],
|
|
69
|
+
[1, -1],
|
|
70
|
+
[-1, 1],
|
|
71
|
+
[-1, -1]
|
|
72
|
+
];
|
|
73
|
+
//#endregion
|
|
74
|
+
export { Area3D, AssetStore3D, Billboard3D, BoneAttachment3D, Camera3D, CharacterBody3D, CharacterController3D, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, Environment3D, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, Flowers3D, Foliage3D, Joint3D, LoftMesh3D, MeshInstance3D, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, PhysicsBody3D, QUARTER_PITCH, Renderer3D, RigidBody3D, StaticBody3D, TERRAIN_THEMES, Terrain3D, Trail3D, Tree3D, VOXEL_PALETTE, VoxelGrid3D, WATER_MAX_RIPPLES, Water3D, buildHeightmap, buildTerrainNav, cameraRelative, createGame3D, enablePhysics3D, horizonColorFromSky, keyboardIntensity, movementState, parseEnvironment3D, registerNodes3D, resolveFlowerDensity, rigPose, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers };
|
|
@@ -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-Dn3yidJw.js";
|
|
7
7
|
import { t as debugSources } from "./debug-draw-CZmOYjL2.js";
|
|
8
|
-
import { A as PhysicsBody3D, N as Node3D, b as Camera3D, f as DirectionalLight3D, l as ModelInstance3D, t as registerNodes3D } from "./register-
|
|
9
|
-
import { n as enablePhysics3D } from "./physics-3d-
|
|
8
|
+
import { A as PhysicsBody3D, N as Node3D, b as Camera3D, f as DirectionalLight3D, l as ModelInstance3D, t as registerNodes3D } from "./register-ysLR3WQS.js";
|
|
9
|
+
import { n as enablePhysics3D } from "./physics-3d-RLNaxRyw.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";
|
|
@@ -182,6 +182,9 @@ varying vec2 vUv;
|
|
|
182
182
|
uniform sampler2D tScene;
|
|
183
183
|
uniform sampler2D tBloom;
|
|
184
184
|
uniform float uStrength;
|
|
185
|
+
uniform float uVignette;
|
|
186
|
+
uniform float uSaturation;
|
|
187
|
+
uniform float uContrast;
|
|
185
188
|
void main() {
|
|
186
189
|
vec3 base = texture2D(tScene, vUv).rgb;
|
|
187
190
|
vec3 glow = texture2D(tBloom, vUv).rgb;
|
|
@@ -192,6 +195,15 @@ void main() {
|
|
|
192
195
|
// tail here (ACES then linear→sRGB); without it the frame comes out dark
|
|
193
196
|
// and oversaturated (the volumetric-clouds pipeline bug, root-caused).
|
|
194
197
|
#include <tonemapping_fragment>
|
|
198
|
+
// color grade AFTER tone mapping (values are display-referred now) and
|
|
199
|
+
// BEFORE the colorspace transform: saturation → contrast → vignette
|
|
200
|
+
vec3 graded = gl_FragColor.rgb;
|
|
201
|
+
float luma = dot(graded, vec3(0.2126, 0.7152, 0.0722));
|
|
202
|
+
graded = mix(vec3(luma), graded, uSaturation);
|
|
203
|
+
graded = (graded - 0.5) * uContrast + 0.5;
|
|
204
|
+
float dist = distance(vUv, vec2(0.5));
|
|
205
|
+
graded *= 1.0 - uVignette * smoothstep(0.3, 0.78, dist);
|
|
206
|
+
gl_FragColor.rgb = max(graded, 0.0);
|
|
195
207
|
#include <colorspace_fragment>
|
|
196
208
|
}
|
|
197
209
|
`;
|
|
@@ -234,7 +246,10 @@ function createBloomCompositeQuad() {
|
|
|
234
246
|
const mesh = quad(COMPOSITE_FRAG, {
|
|
235
247
|
tScene: { value: null },
|
|
236
248
|
tBloom: { value: null },
|
|
237
|
-
uStrength: { value: .85 }
|
|
249
|
+
uStrength: { value: .85 },
|
|
250
|
+
uVignette: { value: 0 },
|
|
251
|
+
uSaturation: { value: 1 },
|
|
252
|
+
uContrast: { value: 1 }
|
|
238
253
|
});
|
|
239
254
|
return {
|
|
240
255
|
mesh,
|
|
@@ -562,6 +577,11 @@ const CLOUD_KEYS = [
|
|
|
562
577
|
"scale"
|
|
563
578
|
];
|
|
564
579
|
const BLOOM_KEYS = ["threshold", "strength"];
|
|
580
|
+
const POST_KEYS = [
|
|
581
|
+
"vignette",
|
|
582
|
+
"saturation",
|
|
583
|
+
"contrast"
|
|
584
|
+
];
|
|
565
585
|
const SHADOW_KEYS = [
|
|
566
586
|
"mapSize",
|
|
567
587
|
"radius",
|
|
@@ -583,6 +603,7 @@ function parseEnvironment3D(env) {
|
|
|
583
603
|
fog: parseFog(env?.fog, env?.sky !== void 0),
|
|
584
604
|
clouds: parseClouds(env?.clouds),
|
|
585
605
|
bloom: parseBloom(env?.bloom),
|
|
606
|
+
post: parsePost(env?.post),
|
|
586
607
|
shadows: parseShadows(env?.shadows)
|
|
587
608
|
};
|
|
588
609
|
}
|
|
@@ -754,6 +775,26 @@ function parseBloom(value) {
|
|
|
754
775
|
strength
|
|
755
776
|
};
|
|
756
777
|
}
|
|
778
|
+
function parsePost(value) {
|
|
779
|
+
if (value === void 0) return null;
|
|
780
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new IncantoError("BAD_FORMAT", `environment.post must be an object ({ vignette?, saturation?, contrast? }), got ${JSON.stringify(value)}.`, { prop: "post" });
|
|
781
|
+
const p = value;
|
|
782
|
+
for (const key of Object.keys(p)) if (!POST_KEYS.includes(key)) throw new IncantoError("BAD_FORMAT", `environment.post has unknown key '${key}'. Valid keys: [${POST_KEYS.join(", ")}].`, {
|
|
783
|
+
prop: "post",
|
|
784
|
+
validOptions: POST_KEYS
|
|
785
|
+
});
|
|
786
|
+
const vignette = numberOr(p.vignette, 0, "post.vignette");
|
|
787
|
+
if (vignette < 0 || vignette > 1) throw new IncantoError("BAD_FORMAT", `environment.post.vignette must be in [0, 1], got ${vignette}.`, { prop: "post" });
|
|
788
|
+
const saturation = numberOr(p.saturation, 1, "post.saturation");
|
|
789
|
+
if (saturation < 0 || saturation > 4) throw new IncantoError("BAD_FORMAT", `environment.post.saturation must be in [0, 4] (1 = neutral), got ${saturation}.`, { prop: "post" });
|
|
790
|
+
const contrast = numberOr(p.contrast, 1, "post.contrast");
|
|
791
|
+
if (contrast < .2 || contrast > 3) throw new IncantoError("BAD_FORMAT", `environment.post.contrast must be in [0.2, 3] (1 = neutral), got ${contrast}.`, { prop: "post" });
|
|
792
|
+
return {
|
|
793
|
+
vignette,
|
|
794
|
+
saturation,
|
|
795
|
+
contrast
|
|
796
|
+
};
|
|
797
|
+
}
|
|
757
798
|
function parseShadows(value) {
|
|
758
799
|
if (value === void 0) return null;
|
|
759
800
|
if (value === false) return false;
|
|
@@ -876,6 +917,10 @@ var Environment3D = class {
|
|
|
876
917
|
get bloom() {
|
|
877
918
|
return this.config.bloom;
|
|
878
919
|
}
|
|
920
|
+
/** Parsed color-grade/vignette config, or null when not declared. */
|
|
921
|
+
get post() {
|
|
922
|
+
return this.config.post;
|
|
923
|
+
}
|
|
879
924
|
/** The live scene fog (color/near/far) the cloud composite fades into, or null. */
|
|
880
925
|
get sceneFog() {
|
|
881
926
|
return this.scene.fog instanceof Fog ? this.scene.fog : null;
|
|
@@ -1601,9 +1646,10 @@ var Renderer3D = class {
|
|
|
1601
1646
|
this.environment.applyUnderwater(underwater);
|
|
1602
1647
|
const clouds = this.environment.clouds;
|
|
1603
1648
|
const bloom = this.environment.bloom;
|
|
1649
|
+
const post = this.environment.post;
|
|
1604
1650
|
if (underwater?.caustics.enabled) this.renderWithCaustics(activeCamera, underwater);
|
|
1605
1651
|
else if (clouds && !underwater) this.renderWithClouds(activeCamera, clouds, threeLight);
|
|
1606
|
-
else if (bloom && !underwater) this.renderWithBloom(activeCamera, bloom);
|
|
1652
|
+
else if ((bloom || post) && !underwater) this.renderWithBloom(activeCamera, bloom, post);
|
|
1607
1653
|
else this.webgl.render(this.threeScene, activeCamera);
|
|
1608
1654
|
}
|
|
1609
1655
|
/**
|
|
@@ -1615,7 +1661,7 @@ var Renderer3D = class {
|
|
|
1615
1661
|
* the scene's tone; the clouds pipeline taught us that lesson)
|
|
1616
1662
|
* Caustics/clouds paths take precedence (composite pipelines don't stack yet).
|
|
1617
1663
|
*/
|
|
1618
|
-
renderWithBloom(camera, bloom) {
|
|
1664
|
+
renderWithBloom(camera, bloom, post = null) {
|
|
1619
1665
|
const buf = this.webgl.getDrawingBufferSize(sizeScratch);
|
|
1620
1666
|
const w = Math.max(1, buf.x);
|
|
1621
1667
|
const h = Math.max(1, buf.y);
|
|
@@ -1652,24 +1698,29 @@ var Renderer3D = class {
|
|
|
1652
1698
|
const blurTarget = this.bloomBlurTarget;
|
|
1653
1699
|
this.webgl.setRenderTarget(this.bloomTarget);
|
|
1654
1700
|
this.webgl.render(this.threeScene, camera);
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1701
|
+
if (bloom) {
|
|
1702
|
+
const bu = this.bloomBrightUniforms;
|
|
1703
|
+
bu.tScene.value = this.bloomTarget.texture;
|
|
1704
|
+
bu.uThreshold.value = bloom.threshold;
|
|
1705
|
+
this.webgl.setRenderTarget(brightTarget);
|
|
1706
|
+
this.webgl.render(this.bloomBrightScene, camera);
|
|
1707
|
+
const blu = this.bloomBlurUniforms;
|
|
1708
|
+
blu.tTex.value = brightTarget.texture;
|
|
1709
|
+
blu.uDir.value.set(1 / hw, 0);
|
|
1710
|
+
this.webgl.setRenderTarget(blurTarget);
|
|
1711
|
+
this.webgl.render(this.bloomBlurScene, camera);
|
|
1712
|
+
blu.tTex.value = blurTarget.texture;
|
|
1713
|
+
blu.uDir.value.set(0, 1 / hh);
|
|
1714
|
+
this.webgl.setRenderTarget(brightTarget);
|
|
1715
|
+
this.webgl.render(this.bloomBlurScene, camera);
|
|
1716
|
+
}
|
|
1669
1717
|
const cu = this.bloomCompositeUniforms;
|
|
1670
1718
|
cu.tScene.value = this.bloomTarget.texture;
|
|
1671
|
-
cu.tBloom.value = brightTarget.texture;
|
|
1672
|
-
cu.uStrength.value = bloom.strength;
|
|
1719
|
+
cu.tBloom.value = bloom ? brightTarget.texture : this.bloomTarget.texture;
|
|
1720
|
+
cu.uStrength.value = bloom ? bloom.strength : 0;
|
|
1721
|
+
cu.uVignette.value = post?.vignette ?? 0;
|
|
1722
|
+
cu.uSaturation.value = post?.saturation ?? 1;
|
|
1723
|
+
cu.uContrast.value = post?.contrast ?? 1;
|
|
1673
1724
|
this.webgl.setRenderTarget(null);
|
|
1674
1725
|
this.webgl.render(this.bloomCompositeScene, camera);
|
|
1675
1726
|
}
|
|
@@ -6,7 +6,7 @@ import { i as resolveRendering, n as attachTouchControls } from "./touch-031PxtC
|
|
|
6
6
|
import { n as registerGameplayBehaviors } from "./gameplay-Dn3yidJw.js";
|
|
7
7
|
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-BD6zgrv_.js";
|
|
8
8
|
import { t as debugSources } from "./debug-draw-CZmOYjL2.js";
|
|
9
|
-
import { n as enablePhysics2D } from "./physics-2d-
|
|
9
|
+
import { n as enablePhysics2D } from "./physics-2d-B6D864oZ.js";
|
|
10
10
|
import { Box3, BufferAttribute, BufferGeometry, Color, LineBasicMaterial, LineSegments, LinearFilter, NearestFilter, OrthographicCamera, Raycaster, SRGBColorSpace, Scene, TextureLoader, Vector2, Vector3, WebGLRenderer } from "three";
|
|
11
11
|
//#region src/2d/assets.ts
|
|
12
12
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { a as Rng, c as JsonValue, d as jsonKind, i as SceneJson, l as jsonClone
|
|
|
2
2
|
import { $ as Node, A as SfxPlayOptions, B as spatialPan, C as RendererStats, D as LogManager, E as LogLevel, F as ROLLOFF_MODELS, G as SynthOptions, H as SFX_PRESET_NAMES, I as RolloffModel, J as MusicManager, K as synthSfx, L as SpatialParams, M as Voice, N as VoicePreset, O as InputMap, P as Listener, Q as BusName, R as Vec3, S as GameStats, T as LogEntry, U as SfxParams, V as SFX_PRESETS, W as SfxWave, X as PlayMusicOptions, Y as MusicTrack, Z as AudioBuses, _ as registeredTypes, a as registerBehavior, b as Scheduler, c as PropDef, d as createNode, et as NodeLifecycle, f as getNodeSchema, g as registerNode, h as mergeStaticSignals, i as getBehavior, j as isAudioContextAvailable, k as SfxEngine, l as PropSchema, m as getNodeType, n as BehaviorCtor, nt as SignalListener, o as registeredBehaviors, p as getNodeSignals, q as MusicBackend, r as clearBehaviors, rt as SceneTree, s as NodeCtor, t as Behavior, tt as Signal, u as clearRegistry, v as Engine, w as Scene, x as EngineStats, y as EngineOptions, z as spatialGain } from "./behavior-Bod1AyJS.js";
|
|
3
3
|
import { n as loadScene, t as LoadSceneOptions } from "./loader-BcUDfNHn.js";
|
|
4
4
|
import { n as ParticleSimConfig, r as ParticleView, t as ParticleSim } from "./particle-sim-CwJ5rI_P.js";
|
|
5
|
-
import { n as AudioPlayer, t as
|
|
5
|
+
import { a as AudioElementLike, i as gridFromRows, n as PathGrid, o as AudioPlayer, r as findPath, t as FindPathOptions } from "./pathfinding-BSiXjd6W.js";
|
|
6
6
|
import { i as auditScene, n as IncantoErrorCode, r as IncantoErrorDetails, t as IncantoError } from "./errors-1dXlIwoR.js";
|
|
7
7
|
|
|
8
8
|
//#region src/core/audio/crossfade.d.ts
|
|
@@ -336,33 +336,6 @@ declare const PARTICLE_PRESET_NAMES: readonly string[];
|
|
|
336
336
|
*/
|
|
337
337
|
declare function applyParticlePreset(target: Record<string, unknown>, presetName: string, schema: PropSchema): void;
|
|
338
338
|
//#endregion
|
|
339
|
-
//#region src/core/pathfinding.d.ts
|
|
340
|
-
/**
|
|
341
|
-
* Grid A* — the pathfinding every top-down/RPG/tower-defense asks for and
|
|
342
|
-
* agents keep re-inventing badly. Pure and dimension-free: cells in, cells
|
|
343
|
-
* out; the caller maps cells to world units (px, meters, tiles).
|
|
344
|
-
*/
|
|
345
|
-
interface PathGrid {
|
|
346
|
-
width: number;
|
|
347
|
-
height: number;
|
|
348
|
-
/** True = impassable. Out-of-bounds is always solid. */
|
|
349
|
-
solid(x: number, y: number): boolean;
|
|
350
|
-
}
|
|
351
|
-
interface FindPathOptions {
|
|
352
|
-
/** Allow diagonal steps (blocked from cutting corners). Default true. */
|
|
353
|
-
diagonal?: boolean;
|
|
354
|
-
/** Abort guard for huge/impossible searches. Default 20000 nodes. */
|
|
355
|
-
maxExpansions?: number;
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* A* from `from` to `to` (inclusive cell coords). Returns the cell path
|
|
359
|
-
* INCLUDING both endpoints, or null when unreachable. Straight steps cost
|
|
360
|
-
* 1, diagonals √2; the heuristic is octile (admissible for both modes).
|
|
361
|
-
*/
|
|
362
|
-
declare function findPath(grid: PathGrid, from: [number, number], to: [number, number], opts?: FindPathOptions): [number, number][] | null;
|
|
363
|
-
/** Build a PathGrid from row-strings ('#' = solid) — tests and tile games. */
|
|
364
|
-
declare function gridFromRows(rows: readonly string[]): PathGrid;
|
|
365
|
-
//#endregion
|
|
366
339
|
//#region src/core/preload.d.ts
|
|
367
340
|
interface PreloadResult {
|
|
368
341
|
/** Urls whose fetch failed — show an error UI instead of pretending success. */
|
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.12.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 };
|
|
@@ -107,4 +107,31 @@ declare class AudioPlayer extends Node {
|
|
|
107
107
|
override update(_dt: number): void;
|
|
108
108
|
}
|
|
109
109
|
//#endregion
|
|
110
|
-
|
|
110
|
+
//#region src/core/pathfinding.d.ts
|
|
111
|
+
/**
|
|
112
|
+
* Grid A* — the pathfinding every top-down/RPG/tower-defense asks for and
|
|
113
|
+
* agents keep re-inventing badly. Pure and dimension-free: cells in, cells
|
|
114
|
+
* out; the caller maps cells to world units (px, meters, tiles).
|
|
115
|
+
*/
|
|
116
|
+
interface PathGrid {
|
|
117
|
+
width: number;
|
|
118
|
+
height: number;
|
|
119
|
+
/** True = impassable. Out-of-bounds is always solid. */
|
|
120
|
+
solid(x: number, y: number): boolean;
|
|
121
|
+
}
|
|
122
|
+
interface FindPathOptions {
|
|
123
|
+
/** Allow diagonal steps (blocked from cutting corners). Default true. */
|
|
124
|
+
diagonal?: boolean;
|
|
125
|
+
/** Abort guard for huge/impossible searches. Default 20000 nodes. */
|
|
126
|
+
maxExpansions?: number;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* A* from `from` to `to` (inclusive cell coords). Returns the cell path
|
|
130
|
+
* INCLUDING both endpoints, or null when unreachable. Straight steps cost
|
|
131
|
+
* 1, diagonals √2; the heuristic is octile (admissible for both modes).
|
|
132
|
+
*/
|
|
133
|
+
declare function findPath(grid: PathGrid, from: [number, number], to: [number, number], opts?: FindPathOptions): [number, number][] | null;
|
|
134
|
+
/** Build a PathGrid from row-strings ('#' = solid) — tests and tile games. */
|
|
135
|
+
declare function gridFromRows(rows: readonly string[]): PathGrid;
|
|
136
|
+
//#endregion
|
|
137
|
+
export { AudioElementLike as a, gridFromRows as i, PathGrid as n, AudioPlayer as o, findPath as r, SpatialPose as s, FindPathOptions as t };
|
|
@@ -99,8 +99,12 @@ var Physics2D = class {
|
|
|
99
99
|
const b = this.byColliderHandle.get(h2);
|
|
100
100
|
if (!a || !b) return;
|
|
101
101
|
const sig = started ? "triggerEnter" : "triggerExit";
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
try {
|
|
103
|
+
a.emit(sig, b);
|
|
104
|
+
b.emit(sig, a);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.error(`incanto: error in a '${sig}' handler (${a.name} ↔ ${b.name}):`, error);
|
|
107
|
+
}
|
|
104
108
|
});
|
|
105
109
|
}
|
|
106
110
|
/** @internal Called by CharacterBody2D.moveAndSlide (during tree fixedUpdate). */
|
|
@@ -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 PhysicsBody3D, C as Terrain3D, D as Joint3D, N as Node3D, O as Area3D, P as validateCollider3D, j as RigidBody3D, k as CharacterBody3D } from "./register-
|
|
4
|
+
import { A as PhysicsBody3D, C as Terrain3D, D as Joint3D, N as Node3D, O as Area3D, P as validateCollider3D, j as RigidBody3D, k as CharacterBody3D } from "./register-ysLR3WQS.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({
|
|
@@ -124,8 +124,12 @@ var Physics3D = class {
|
|
|
124
124
|
const b = this.byColliderHandle.get(h2);
|
|
125
125
|
if (!a || !b) return;
|
|
126
126
|
const sig = started ? "triggerEnter" : "triggerExit";
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
try {
|
|
128
|
+
a.emit(sig, b);
|
|
129
|
+
b.emit(sig, a);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error(`incanto: error in a '${sig}' handler (${a.name} ↔ ${b.name}):`, error);
|
|
132
|
+
}
|
|
129
133
|
});
|
|
130
134
|
}
|
|
131
135
|
/** @internal Called by CharacterBody3D.moveAndSlide (during tree fixedUpdate). */
|
|
@@ -399,6 +403,38 @@ var Physics3D = class {
|
|
|
399
403
|
node: this.byColliderHandle.get(hit.collider.handle) ?? null
|
|
400
404
|
};
|
|
401
405
|
}
|
|
406
|
+
/**
|
|
407
|
+
* Sweep a sphere of `radius` from `origin` along `dir` — a THICK ray. The
|
|
408
|
+
* spring-arm camera probe uses this instead of `castRay`: a thin ray that
|
|
409
|
+
* skims 10 cm over a wall reports "clear" while the camera's near plane
|
|
410
|
+
* still clips the wall; the ball's radius covers that band. Same filters
|
|
411
|
+
* as `castRay` (sensors never hit; `staticOnly` ignores dynamic/kinematic).
|
|
412
|
+
* Returns the travel distance of the sphere CENTER, or null when clear.
|
|
413
|
+
*/
|
|
414
|
+
castSphere(origin, dir, radius, maxLen, exclude, opts) {
|
|
415
|
+
const R = this.R;
|
|
416
|
+
const excludeEntry = exclude ? this.entries.get(exclude) : void 0;
|
|
417
|
+
const flags = opts?.staticOnly ? R.QueryFilterFlags.EXCLUDE_DYNAMIC | R.QueryFilterFlags.EXCLUDE_KINEMATIC : void 0;
|
|
418
|
+
const hit = this.world.castShape({
|
|
419
|
+
x: origin[0],
|
|
420
|
+
y: origin[1],
|
|
421
|
+
z: origin[2]
|
|
422
|
+
}, {
|
|
423
|
+
x: 0,
|
|
424
|
+
y: 0,
|
|
425
|
+
z: 0,
|
|
426
|
+
w: 1
|
|
427
|
+
}, {
|
|
428
|
+
x: dir[0],
|
|
429
|
+
y: dir[1],
|
|
430
|
+
z: dir[2]
|
|
431
|
+
}, new R.Ball(radius), 0, maxLen, true, flags, void 0, excludeEntry?.collider, excludeEntry?.body, (collider) => !collider.isSensor());
|
|
432
|
+
if (!hit) return null;
|
|
433
|
+
return {
|
|
434
|
+
distance: hit.time_of_impact,
|
|
435
|
+
node: this.byColliderHandle.get(hit.collider.handle) ?? null
|
|
436
|
+
};
|
|
437
|
+
}
|
|
402
438
|
};
|
|
403
439
|
const quatScratch = new Quaternion();
|
|
404
440
|
const eulerScratch = new Euler();
|
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-B2fewJUy.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-C_xf4gm9.js").then((n) => n.n)).createGame2D(o)))(opts);
|
|
160
160
|
if (disposed) {
|
|
161
161
|
next.dispose();
|
|
162
162
|
return;
|
|
@@ -2017,6 +2017,10 @@ const CAM_COLLISION_MARGIN = .3;
|
|
|
2017
2017
|
const CAM_COLLISION_MIN_DIST = .4;
|
|
2018
2018
|
/** Ground backstop: keep the camera at least this high above whatever is below it. */
|
|
2019
2019
|
const CAM_GROUND_CLEARANCE = .3;
|
|
2020
|
+
/** Spring-arm probe thickness: a THIN ray that skims 10 cm above a wall reports
|
|
2021
|
+
* "clear" while the wall still fills the frame — the sphere's radius covers the
|
|
2022
|
+
* near-plane band around the boom (the Emberwood hedge-maze lesson). */
|
|
2023
|
+
const CAM_PROBE_RADIUS = .25;
|
|
2020
2024
|
const eulerScratch = new Euler();
|
|
2021
2025
|
const quatScratch = new Quaternion();
|
|
2022
2026
|
const matrixScratch$3 = new Matrix4();
|
|
@@ -2285,7 +2289,7 @@ var CharacterController3D = class extends Node3D {
|
|
|
2285
2289
|
if (this.cameraCollision && this.view !== "firstPerson") {
|
|
2286
2290
|
const physics = body._physics3d;
|
|
2287
2291
|
if (physics) {
|
|
2288
|
-
target = springArmCamera(eye, target, (o, dr, len) => physics.
|
|
2292
|
+
target = springArmCamera(eye, target, (o, dr, len) => physics.castSphere(o, dr, CAM_PROBE_RADIUS, len, body, { staticOnly: true })?.distance ?? null, CAM_COLLISION_MARGIN, CAM_COLLISION_MIN_DIST);
|
|
2289
2293
|
target = clampCameraAboveGround(target, (o, len) => physics.castRay(o, [
|
|
2290
2294
|
0,
|
|
2291
2295
|
-1,
|
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-Dn3yidJw.js";
|
|
8
8
|
import { t as registerNodes2D } from "./register-BD6zgrv_.js";
|
|
9
|
-
import { t as registerNodes3D } from "./register-
|
|
9
|
+
import { t as registerNodes3D } from "./register-ysLR3WQS.js";
|
|
10
10
|
import { t as registerNodesNet } from "./register-Cwc-yCYx.js";
|
|
11
11
|
//#region src/test/index.ts
|
|
12
12
|
/**
|
|
@@ -124,10 +124,10 @@ async function runScript(json, opts) {
|
|
|
124
124
|
engine.setScene(scene);
|
|
125
125
|
const physics = opts.physics ?? "auto";
|
|
126
126
|
if (physics === "2d" || physics === "auto" && scene.dimension === "2d") {
|
|
127
|
-
const { enablePhysics2D } = await import("./physics-2d-
|
|
127
|
+
const { enablePhysics2D } = await import("./physics-2d-B6D864oZ.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-RLNaxRyw.js").then((n) => n.r);
|
|
131
131
|
await enablePhysics3D(engine);
|
|
132
132
|
}
|
|
133
133
|
const failures = [];
|
|
@@ -229,10 +229,10 @@ async function createPlaySession(json, opts = {}) {
|
|
|
229
229
|
engine.setScene(scene);
|
|
230
230
|
const physics = opts.physics ?? "auto";
|
|
231
231
|
if (physics === "2d" || physics === "auto" && scene.dimension === "2d") {
|
|
232
|
-
const { enablePhysics2D } = await import("./physics-2d-
|
|
232
|
+
const { enablePhysics2D } = await import("./physics-2d-B6D864oZ.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-RLNaxRyw.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-s0DZuroe.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};
|