incanto 0.32.0 → 0.33.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.d.ts +59 -2
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +8 -3
- package/dist/3d.js +4 -4
- package/dist/{behavior-D_jMpFh8.d.ts → behavior-CKwTCjfR.d.ts} +140 -1
- package/dist/{create-game-bKHgHcsZ.js → create-game-D2QU5x7S.js} +13 -6
- package/dist/{create-game-gXI7PYl0.js → create-game-sFuTLqjD.js} +11 -5
- package/dist/debug.d.ts +1 -1
- package/dist/{duplicate-KRPtUtzl.js → duplicate-BgnG1Lqz.js} +1 -1
- package/dist/editor.js +35 -0
- package/dist/{environment-presets--DigHNg4.js → environment-presets-CQtEGogB.js} +2 -2
- package/dist/{gameplay-BftxM_It.js → gameplay-BpQCbABv.js} +90 -2
- package/dist/gameplay.d.ts +1 -1
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +125 -23
- package/dist/index.js +5 -58
- package/dist/{loader-BlaRQGaA.js → loader-Buk8Bu1h.js} +53 -0
- package/dist/{loader-BYBrqTxP.d.ts → loader-COn5fS0o.d.ts} +1 -1
- package/dist/net.d.ts +1 -1
- package/dist/net.js +3 -3
- package/dist/{pathfinding-BwhqPD3i.d.ts → pathfinding-DUw9mir9.d.ts} +1 -1
- package/dist/{physics-2d-D9wquBvK.js → physics-2d-DjXR5DMu.js} +12 -2
- package/dist/{physics-3d-CnPygVGo.js → physics-3d-DF8npb1O.js} +55 -9
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-Dzkd6-os.js → register-CscIzJEO.js} +551 -13
- package/dist/{register-CUY284Is.js → register-CtI-itec.js} +2 -2
- package/dist/{register-tkR_8tWg.js → register-FIJtNbub.js} +145 -8
- package/dist/{test-WwRIlXsK.js → test-BRxLd2jH.js} +10 -10
- package/dist/test.d.ts +2 -2
- package/dist/test.js +1 -1
- package/dist/vite.js +1 -1
- package/editor/assets/{agent8-C5k1nTCH.js → agent8-BdDP3xKW.js} +1 -1
- package/editor/assets/{debug-BT_0mjk-.js → debug-DbjTyTlC.js} +1 -1
- package/editor/assets/{index-gfyrByWw.js → index-BWCudoz1.js} +90 -90
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +520 -0
- package/skills/incanto-audio.md +43 -0
- package/skills/incanto-building-2d-games.md +36 -0
- package/skills/incanto-hud.md +41 -0
- package/skills/incanto-node-reference.md +89 -0
- package/skills/incanto-physics-and-input.md +50 -0
- package/templates-app/beacon-isle-3d/docs/project-3d-rules.md +40 -19
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/docs/project-3d-rules.md +41 -19
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/docs/project-3d-rules.md +40 -19
- package/templates-app/village-quest-3d/package.json +1 -1
package/dist/2d.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { C as RendererStats, S as GameStats,
|
|
1
|
+
import { C as RendererStats, N as Scene$1, S as GameStats, at as Node, b as Scheduler, l as PropSchema, n as BehaviorCtor, v as Engine } from "./behavior-CKwTCjfR.js";
|
|
2
2
|
import { n as DiagnosticSink, t as EditorSwitchOptions } from "./editor-switch-BJb-CWfA.js";
|
|
3
3
|
import { i as SceneJson, s as JsonObject } from "./schema-CcoWb32N.js";
|
|
4
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
4
|
+
import { t as LoadSceneOptions } from "./loader-COn5fS0o.js";
|
|
5
5
|
import { t as ParticleSim } from "./particle-sim-CwJ5rI_P.js";
|
|
6
6
|
import { Group, Mesh, Object3D, Scene, Texture } from "three";
|
|
7
7
|
import * as RapierNs from "@dimforge/rapier2d-compat";
|
|
@@ -144,6 +144,22 @@ declare class CharacterBody2D extends PhysicsBody2D {
|
|
|
144
144
|
/** @internal Updated by Physics2D.moveAndSlide. */
|
|
145
145
|
_grounded: boolean;
|
|
146
146
|
moveAndSlide(): void;
|
|
147
|
+
/** @internal Set by the physics step from the KCC's resolved collisions. */
|
|
148
|
+
_onWall: number;
|
|
149
|
+
/** @internal */
|
|
150
|
+
_onCeiling: boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Touching a wall, and which side (-1 left, +1 right, 0 neither).
|
|
153
|
+
*
|
|
154
|
+
* Wall jump and wall slide are unbuildable without it — not awkward to build,
|
|
155
|
+
* impossible: `isOnFloor()` was the only surface a character could report, so
|
|
156
|
+
* even a hand-written behavior had nothing to ask.
|
|
157
|
+
*/
|
|
158
|
+
isOnWall(): boolean;
|
|
159
|
+
/** -1 the wall is to the left, +1 to the right, 0 no wall. */
|
|
160
|
+
wallSide(): number;
|
|
161
|
+
/** Head hit something — cut the jump short, the way every platformer does. */
|
|
162
|
+
isOnCeiling(): boolean;
|
|
147
163
|
isOnFloor(): boolean;
|
|
148
164
|
}
|
|
149
165
|
//#endregion
|
|
@@ -321,6 +337,11 @@ interface Game2D {
|
|
|
321
337
|
sourceJson: SceneJson;
|
|
322
338
|
renderer: GameRenderer;
|
|
323
339
|
physics: Physics2D | null;
|
|
340
|
+
/**
|
|
341
|
+
* The node under a screen pixel, or null. The raycast the renderer already
|
|
342
|
+
* does — reachable now without holding the renderer.
|
|
343
|
+
*/
|
|
344
|
+
pick(x: number, y: number): Node | null;
|
|
324
345
|
/** Engine + renderer perf counters in one read (fps/nodes/triangles/…). */
|
|
325
346
|
stats(): GameStats;
|
|
326
347
|
/**
|
|
@@ -463,18 +484,54 @@ declare class Camera2D extends Node2D {
|
|
|
463
484
|
* - `platformer`: x movement + gravity (from the scene `physics.gravity[1]`,
|
|
464
485
|
* default 980) + jump (`jumpHeight` px → impulse √(2·g·h))
|
|
465
486
|
* - `topDown`: full-axis movement, no gravity
|
|
487
|
+
*
|
|
488
|
+
* ## Why the extra platformer props exist
|
|
489
|
+
*
|
|
490
|
+
* A jump that only works while `isOnFloor()` is true feels BROKEN, and players
|
|
491
|
+
* do not report it as "the coyote time is missing" — they report the game as
|
|
492
|
+
* unresponsive. The whole schema used to be five props, so a JSON-only game got
|
|
493
|
+
* a character that felt wrong and could not drive `AnimatedSprite2D.play('run')`
|
|
494
|
+
* either. `examples/platformer-2d` hand-rolls all of this in a 541-line
|
|
495
|
+
* behavior; these are those constants, as props.
|
|
496
|
+
*
|
|
497
|
+
* Every one defaults to OFF (0 / 1 / false), so an existing scene behaves
|
|
498
|
+
* exactly as before until it asks for something.
|
|
466
499
|
*/
|
|
467
500
|
declare class CharacterController2D extends Node {
|
|
468
501
|
static override readonly typeName: string;
|
|
469
502
|
static readonly props: PropSchema;
|
|
503
|
+
static readonly signals: readonly string[];
|
|
470
504
|
mode: string;
|
|
471
505
|
maxSpeed: number;
|
|
472
506
|
/** Pixels (platformer mode). */
|
|
473
507
|
jumpHeight: number;
|
|
474
508
|
moveAction: string;
|
|
475
509
|
jumpAction: string;
|
|
510
|
+
coyoteSeconds: number;
|
|
511
|
+
jumpBufferSeconds: number;
|
|
512
|
+
jumpCutMultiplier: number;
|
|
513
|
+
maxJumps: number;
|
|
514
|
+
dashSpeed: number;
|
|
515
|
+
dashSeconds: number;
|
|
516
|
+
dashAction: string;
|
|
517
|
+
wallSlideSpeed: number;
|
|
518
|
+
wallJumpImpulse: number[];
|
|
519
|
+
/** What the character is doing — drive `AnimatedSprite2D.play(state)` off it. */
|
|
520
|
+
state: "idle" | "run" | "jump" | "fall" | "wallSlide" | "dash";
|
|
521
|
+
private coyoteLeft;
|
|
522
|
+
private bufferLeft;
|
|
523
|
+
private jumpsUsed;
|
|
524
|
+
private dashLeft;
|
|
525
|
+
private dashDir;
|
|
526
|
+
private rising;
|
|
476
527
|
override onReady(): void;
|
|
477
528
|
override fixedUpdate(dt: number): void;
|
|
529
|
+
/**
|
|
530
|
+
* Emits `movementStateChanged(state)` on a change — the 3D sibling has had
|
|
531
|
+
* this since it shipped, and it is what drives `AnimatedSprite2D.play(...)`
|
|
532
|
+
* from scene JSON instead of a behavior polling velocities.
|
|
533
|
+
*/
|
|
534
|
+
private setState;
|
|
478
535
|
}
|
|
479
536
|
//#endregion
|
|
480
537
|
//#region src/2d/nodes/color-rect-2d.d.ts
|
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-
|
|
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-
|
|
4
|
-
import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-
|
|
2
|
+
import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-D2QU5x7S.js";
|
|
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-FIJtNbub.js";
|
|
4
|
+
import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-DjXR5DMu.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
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { C as RendererStats, S as GameStats,
|
|
1
|
+
import { C as RendererStats, N as Scene$1, S as GameStats, at as Node, b as Scheduler, l as PropSchema, n as BehaviorCtor, v as Engine } from "./behavior-CKwTCjfR.js";
|
|
2
2
|
import { n as DiagnosticSink, t as EditorSwitchOptions } from "./editor-switch-BJb-CWfA.js";
|
|
3
3
|
import { i as SceneJson, s as JsonObject } from "./schema-CcoWb32N.js";
|
|
4
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
4
|
+
import { t as LoadSceneOptions } from "./loader-COn5fS0o.js";
|
|
5
5
|
import { t as ParticleSim } from "./particle-sim-CwJ5rI_P.js";
|
|
6
|
-
import { n as PathGrid, s as SpatialPose } from "./pathfinding-
|
|
6
|
+
import { n as PathGrid, s as SpatialPose } from "./pathfinding-DUw9mir9.js";
|
|
7
7
|
import { AnimationClip, AnimationMixer, BufferGeometry, Color, DirectionalLight, Group, InstancedMesh, Mesh, MeshPhysicalMaterial, Object3D, PerspectiveCamera, Scene, ShaderMaterial, Vector3, WebGLRenderer } from "three";
|
|
8
8
|
import { VRM } from "@pixiv/three-vrm";
|
|
9
9
|
import { Sky } from "three/examples/jsm/objects/Sky.js";
|
|
@@ -544,6 +544,11 @@ interface Game3D {
|
|
|
544
544
|
sourceJson: SceneJson;
|
|
545
545
|
renderer: GameRenderer;
|
|
546
546
|
physics: Physics3D | null;
|
|
547
|
+
/**
|
|
548
|
+
* The node under a screen pixel, or null. The raycast the renderer already
|
|
549
|
+
* does — reachable now without holding the renderer.
|
|
550
|
+
*/
|
|
551
|
+
pick(x: number, y: number): Node | null;
|
|
547
552
|
/** Engine + renderer perf counters in one read (fps/nodes/triangles/…). */
|
|
548
553
|
stats(): GameStats;
|
|
549
554
|
/**
|
package/dist/3d.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
2
|
-
import { A as Water3D, F as PhysicsBody3D, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D, V as WATER_MAX_RIPPLES, j as WATER_CUTOUT_MAX } from "./gameplay-
|
|
3
|
-
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-
|
|
4
|
-
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, 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, V as movementState, _ 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
|
|
2
|
+
import { A as Water3D, F as PhysicsBody3D, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D, V as WATER_MAX_RIPPLES, j as WATER_CUTOUT_MAX } from "./gameplay-BpQCbABv.js";
|
|
3
|
+
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-sFuTLqjD.js";
|
|
4
|
+
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, 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, V as movementState, _ 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-CQtEGogB.js";
|
|
5
5
|
import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
|
|
6
|
-
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-
|
|
6
|
+
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-DF8npb1O.js";
|
|
7
7
|
//#region src/3d/environment-runtime.ts
|
|
8
8
|
/**
|
|
9
9
|
* Live environment editing — the renderer re-applies `scene.environment`
|
|
@@ -298,6 +298,14 @@ declare class AudioBuses {
|
|
|
298
298
|
/** Final gain for a sound on `bus` with its own `sourceVolume` (all clamped). */
|
|
299
299
|
effectiveVolume(bus: BusName, sourceVolume: number): number;
|
|
300
300
|
/** Clamp + finite-guard a new value; emit only on a real change. */
|
|
301
|
+
/**
|
|
302
|
+
* Write THEN emit.
|
|
303
|
+
*
|
|
304
|
+
* This used to emit from inside the expression assigning the field, so every
|
|
305
|
+
* listener of `changed` read the OLD value — including the thing the signal
|
|
306
|
+
* exists for ("live re-gain of playing sounds"), which therefore re-gained to
|
|
307
|
+
* the volume you just left.
|
|
308
|
+
*/
|
|
301
309
|
private assign;
|
|
302
310
|
}
|
|
303
311
|
//#endregion
|
|
@@ -595,6 +603,25 @@ declare class InputMap {
|
|
|
595
603
|
private detach;
|
|
596
604
|
/** Load (or extend with) scene-JSON action declarations. Hard-validates shape. */
|
|
597
605
|
declare(decls: Record<string, unknown>): void;
|
|
606
|
+
/**
|
|
607
|
+
* Where the pointer is, in CANVAS pixels (top-left origin), or null when it
|
|
608
|
+
* has never been over the canvas.
|
|
609
|
+
*
|
|
610
|
+
* This is what a click-driven game asks for. `pointerDelta()` answers "how far
|
|
611
|
+
* did the mouse move" — the mouse-look question — and for a whole class of
|
|
612
|
+
* genres that is the wrong question and the only one the engine could answer.
|
|
613
|
+
* Pair it with `renderer.pick(x, y)` to get the node under the cursor.
|
|
614
|
+
*/
|
|
615
|
+
pointerPosition(): {
|
|
616
|
+
x: number;
|
|
617
|
+
y: number;
|
|
618
|
+
} | null;
|
|
619
|
+
/**
|
|
620
|
+
* @internal Feed a pointer position. `target` scales client → canvas pixels
|
|
621
|
+
* so a CSS-stretched canvas still reports coordinates its renderer can use.
|
|
622
|
+
*/
|
|
623
|
+
setPointerPosition(clientX: number, clientY: number, target?: HTMLElement): void;
|
|
624
|
+
private pointerPos;
|
|
598
625
|
/** Feed a key state change (code = KeyboardEvent.code, e.g. 'Space', 'KeyW'). */
|
|
599
626
|
handleKey(code: string, isDown: boolean): void;
|
|
600
627
|
private readonly injectedDown;
|
|
@@ -699,6 +726,17 @@ declare class InputMap {
|
|
|
699
726
|
isPressed(action: string): boolean;
|
|
700
727
|
justPressed(action: string): boolean;
|
|
701
728
|
justReleased(action: string): boolean;
|
|
729
|
+
/**
|
|
730
|
+
* Mouse button state WITHOUT declaring an action for it.
|
|
731
|
+
*
|
|
732
|
+
* A click on a tile is not a bindable action — there is no key to remap, and
|
|
733
|
+
* asking a match-3 to declare `"click": { "keys": ["Mouse0"] }` in every scene
|
|
734
|
+
* is ceremony. Buttons already live in the key set as `Mouse0`/`Mouse1`/…;
|
|
735
|
+
* these read them directly. 0 left, 1 middle, 2 right.
|
|
736
|
+
*/
|
|
737
|
+
mousePressed(button?: number): boolean;
|
|
738
|
+
mouseJustPressed(button?: number): boolean;
|
|
739
|
+
mouseJustReleased(button?: number): boolean;
|
|
702
740
|
/** Normalized direction for a vector2 action (y-down: up = -y). */
|
|
703
741
|
getVector(action: string): {
|
|
704
742
|
x: number;
|
|
@@ -753,6 +791,89 @@ declare class Scene {
|
|
|
753
791
|
toJSON(): SceneJson;
|
|
754
792
|
}
|
|
755
793
|
//#endregion
|
|
794
|
+
//#region src/core/save.d.ts
|
|
795
|
+
/**
|
|
796
|
+
* Namespaced game persistence — high scores, unlocks, settings. localStorage
|
|
797
|
+
* in the browser, in-memory headless (tests and SSR stay green). Values are
|
|
798
|
+
* JSON round-tripped, so what you get back is what you saved.
|
|
799
|
+
*
|
|
800
|
+
* const save = createSaveStore('my-game');
|
|
801
|
+
* save.set('highScore', 4200);
|
|
802
|
+
* const best = save.get('highScore', 0);
|
|
803
|
+
*/
|
|
804
|
+
interface SaveStore {
|
|
805
|
+
get<T extends JsonValue>(key: string, fallback: T): T;
|
|
806
|
+
set(key: string, value: JsonValue): void;
|
|
807
|
+
remove(key: string): void;
|
|
808
|
+
/** Wipe THIS namespace only. */
|
|
809
|
+
clear(): void;
|
|
810
|
+
}
|
|
811
|
+
declare function createSaveStore(namespace: string): SaveStore;
|
|
812
|
+
//#endregion
|
|
813
|
+
//#region src/core/settings.d.ts
|
|
814
|
+
/** One of three tiers, resolved once at boot and adjustable in an options menu. */
|
|
815
|
+
type QualityTier = "low" | "medium" | "high";
|
|
816
|
+
interface SettingsValues {
|
|
817
|
+
master: number;
|
|
818
|
+
sfx: number;
|
|
819
|
+
music: number;
|
|
820
|
+
muted: boolean;
|
|
821
|
+
quality: QualityTier;
|
|
822
|
+
/** Mouse/stick look sensitivity multiplier. */
|
|
823
|
+
sensitivity: number;
|
|
824
|
+
invertY: boolean;
|
|
825
|
+
/** Reduce camera shake, flashes and other motion. */
|
|
826
|
+
reduceMotion: boolean;
|
|
827
|
+
}
|
|
828
|
+
/** What a device probe can see without a GPU context. */
|
|
829
|
+
interface DeviceHints {
|
|
830
|
+
hardwareConcurrency?: number;
|
|
831
|
+
deviceMemory?: number;
|
|
832
|
+
coarsePointer?: boolean;
|
|
833
|
+
maxTextureSize?: number;
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* A default tier from what the browser will admit to.
|
|
837
|
+
*
|
|
838
|
+
* Deliberately crude: this picks a STARTING point, and the options menu is the
|
|
839
|
+
* real answer. A phone that reports four cores and a coarse pointer should not
|
|
840
|
+
* open on the setting tuned for a desktop GPU.
|
|
841
|
+
*/
|
|
842
|
+
declare function suggestQuality(hints: DeviceHints): QualityTier;
|
|
843
|
+
/** Read what this environment will tell us, safely, without touching WebGL. */
|
|
844
|
+
declare function readDeviceHints(): DeviceHints;
|
|
845
|
+
declare class Settings {
|
|
846
|
+
/** Fires after any change, with the key that changed. */
|
|
847
|
+
readonly changed: Signal<[keyof SettingsValues]>;
|
|
848
|
+
private readonly store;
|
|
849
|
+
private readonly values;
|
|
850
|
+
constructor(namespace?: string, store?: SaveStore);
|
|
851
|
+
get<K extends keyof SettingsValues>(key: K): SettingsValues[K];
|
|
852
|
+
set<K extends keyof SettingsValues>(key: K, value: SettingsValues[K]): void;
|
|
853
|
+
/** Every value at once — for an options screen, or a save-file dump. */
|
|
854
|
+
all(): SettingsValues;
|
|
855
|
+
/** Back to defaults, on disk too. */
|
|
856
|
+
reset(): void;
|
|
857
|
+
/**
|
|
858
|
+
* Push the saved volumes into the engine's buses, and keep writing them back
|
|
859
|
+
* whenever anything changes them.
|
|
860
|
+
*
|
|
861
|
+
* The subscription is the point: a game that sets `engine.audio.music = 0.4`
|
|
862
|
+
* from a slider has already persisted it, without knowing this class exists.
|
|
863
|
+
*/
|
|
864
|
+
bindAudio(audio: AudioBuses): () => void;
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* What a quality tier MEANS, as an environment patch.
|
|
868
|
+
*
|
|
869
|
+
* Only the levers that actually cost: shadows, post, clouds, and the resolution
|
|
870
|
+
* the renderer draws at. Deliberately an `environment` patch, because
|
|
871
|
+
* `setEnvironment3D(engine, patch)` already applies one live and validated —
|
|
872
|
+
* this is not a second rendering pipeline, it is three presets for the one that
|
|
873
|
+
* exists.
|
|
874
|
+
*/
|
|
875
|
+
declare function qualityEnvironment(tier: QualityTier): Record<string, JsonValue>;
|
|
876
|
+
//#endregion
|
|
756
877
|
//#region src/core/stats.d.ts
|
|
757
878
|
/**
|
|
758
879
|
* Performance-stats shapes — pure data, importable everywhere (core stays
|
|
@@ -824,9 +945,27 @@ declare class Engine {
|
|
|
824
945
|
readonly rng: Rng;
|
|
825
946
|
/** The engine log channel (debug overlay + headless harness tail this). */
|
|
826
947
|
readonly log: LogManager;
|
|
948
|
+
/**
|
|
949
|
+
* Screen pixel → the node under it, when a renderer has offered one.
|
|
950
|
+
*
|
|
951
|
+
* The raycast has always existed (`Renderer3D.pick` / `Renderer2D.pick`) and
|
|
952
|
+
* was reachable only from whoever held the renderer — so a Behavior, which
|
|
953
|
+
* holds a node, could not use it. Every mouse-driven genre needs exactly this
|
|
954
|
+
* and had no way to ask. Instance-scoped, set by the renderer on construction
|
|
955
|
+
* and cleared on dispose; null when nothing renders (headless).
|
|
956
|
+
*/
|
|
957
|
+
picker: ((x: number, y: number) => Node | null) | null;
|
|
827
958
|
/** Global volume buses — `master` × `sfx`/`music` gain + `muted`. AudioPlayer
|
|
828
959
|
* routes its volume through this; games set it for global volume/mute. */
|
|
829
960
|
readonly audio: AudioBuses;
|
|
961
|
+
/**
|
|
962
|
+
* Persisted player settings — volume, quality, sensitivity.
|
|
963
|
+
*
|
|
964
|
+
* `createSaveStore` was good and had zero callers, so every game's volume
|
|
965
|
+
* reset on reload. Reading it here costs nothing (localStorage, once) and
|
|
966
|
+
* `bindAudio` makes the volumes write themselves.
|
|
967
|
+
*/
|
|
968
|
+
readonly settings: Settings;
|
|
830
969
|
/** Low-latency procedural-SFX player (WebAudio, headless-safe). AudioPlayer
|
|
831
970
|
* presets play through it; games may call `engine.sfx.play(...)` directly. */
|
|
832
971
|
readonly sfx: SfxEngine;
|
|
@@ -1035,4 +1174,4 @@ declare function registeredBehaviors(): string[];
|
|
|
1035
1174
|
/** Test isolation helper. */
|
|
1036
1175
|
declare function clearBehaviors(): void;
|
|
1037
1176
|
//#endregion
|
|
1038
|
-
export {
|
|
1177
|
+
export { MusicBackend as $, suggestQuality as A, Listener as B, RendererStats as C, SettingsValues as D, Settings as E, SfxEngine as F, spatialGain as G, RolloffModel as H, SfxPlayOptions as I, SFX_PRESET_NAMES as J, spatialPan as K, isAudioContextAvailable as L, createSaveStore as M, Scene as N, qualityEnvironment as O, InputMap as P, synthSfx as Q, Voice as R, GameStats as S, QualityTier as T, SpatialParams as U, ROLLOFF_MODELS as V, Vec3 as W, SfxWave as X, SfxParams as Y, SynthOptions as Z, registeredTypes as _, registerBehavior as a, Node as at, Scheduler as b, PropDef as c, LogEntry as ct, createNode as d, Signal as dt, MusicManager as et, getNodeSchema as f, SignalListener as ft, registerNode as g, mergeStaticSignals as h, getBehavior as i, BusName as it, SaveStore as j, readDeviceHints as k, PropSchema as l, LogLevel as lt, getNodeType as m, BehaviorCtor as n, PlayMusicOptions as nt, registeredBehaviors as o, NodeLifecycle as ot, getNodeSignals as p, SFX_PRESETS as q, clearBehaviors as r, AudioBuses as rt, NodeCtor as s, SceneTree as st, Behavior as t, MusicTrack as tt, clearRegistry as u, LogManager as ut, Engine as v, DeviceHints as w, EngineStats as x, EngineOptions as y, VoicePreset as z };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { m as diagnose, n as loadScene, o as computeViewport, s as resolveViewport, y as registerBehavior } from "./loader-
|
|
3
|
-
import {
|
|
2
|
+
import { m as diagnose, n as loadScene, o as computeViewport, s as resolveViewport, y as registerBehavior } from "./loader-Buk8Bu1h.js";
|
|
3
|
+
import { h as Engine, m as AudioPlayer } from "./register-CscIzJEO.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
5
|
import { i as resolveRendering, n as attachTouchControls } from "./touch-BoNg_MnF.js";
|
|
6
6
|
import { i as openBundledEditor, n as crossFade, r as devServerLibrary, t as teardown } from "./teardown-ByzfDPyu.js";
|
|
7
|
-
import { n as registerGameplayBehaviors } from "./gameplay-
|
|
8
|
-
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-
|
|
7
|
+
import { n as registerGameplayBehaviors } from "./gameplay-BpQCbABv.js";
|
|
8
|
+
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-FIJtNbub.js";
|
|
9
9
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
10
|
-
import { n as enablePhysics2D } from "./physics-2d-
|
|
10
|
+
import { n as enablePhysics2D } from "./physics-2d-DjXR5DMu.js";
|
|
11
11
|
import { Box3, BufferAttribute, BufferGeometry, Color, LineBasicMaterial, LineSegments, LinearFilter, NearestFilter, OrthographicCamera, Raycaster, SRGBColorSpace, Scene, TextureLoader, Vector2, Vector3, WebGLRenderer } from "three";
|
|
12
12
|
//#region src/2d/assets.ts
|
|
13
13
|
/**
|
|
@@ -274,9 +274,11 @@ var Renderer2D = class {
|
|
|
274
274
|
}, globalThis.devicePixelRatio ?? 1, opts);
|
|
275
275
|
this.webgl = new WebGLRenderer({
|
|
276
276
|
canvas: opts.canvas,
|
|
277
|
-
antialias: rendering.antialias
|
|
277
|
+
antialias: rendering.antialias,
|
|
278
|
+
preserveDrawingBuffer: rendering.preserveDrawingBuffer
|
|
278
279
|
});
|
|
279
280
|
this.webgl.info.autoReset = false;
|
|
281
|
+
this.engine.picker = (x, y) => this.pick(x, y);
|
|
280
282
|
this.webgl.setPixelRatio(rendering.pixelRatio);
|
|
281
283
|
this.webgl.info.autoReset = false;
|
|
282
284
|
this.debugLines = new LineSegments(new BufferGeometry(), new LineBasicMaterial({
|
|
@@ -484,6 +486,7 @@ var Renderer2D = class {
|
|
|
484
486
|
};
|
|
485
487
|
}
|
|
486
488
|
dispose() {
|
|
489
|
+
if (this.engine.picker) this.engine.picker = null;
|
|
487
490
|
this.disconnect();
|
|
488
491
|
for (const scene of [this.worldScene, this.uiScene]) scene.traverse((obj) => {
|
|
489
492
|
const mesh = obj;
|
|
@@ -541,6 +544,7 @@ async function createGame2D(opts) {
|
|
|
541
544
|
const keyboard = opts.keyboard ?? (typeof window !== "undefined" ? window : false);
|
|
542
545
|
if (keyboard) engine.input.attachKeyboard(keyboard);
|
|
543
546
|
cleanups.push(wireAudioUnlock(engine, scene.root, opts.canvas));
|
|
547
|
+
cleanups.push(engine.settings.bindAudio(engine.audio));
|
|
544
548
|
const touchMode = opts.touch ?? "auto";
|
|
545
549
|
if (touchMode !== false) {
|
|
546
550
|
const host = opts.touchContainer ?? opts.canvas.parentElement ?? null;
|
|
@@ -627,6 +631,9 @@ async function createGame2D(opts) {
|
|
|
627
631
|
sourceJson,
|
|
628
632
|
renderer,
|
|
629
633
|
physics,
|
|
634
|
+
pick(x, y) {
|
|
635
|
+
return engine.picker?.(x, y) ?? null;
|
|
636
|
+
},
|
|
630
637
|
stats() {
|
|
631
638
|
return {
|
|
632
639
|
triangles: 0,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { m as diagnose, n as loadScene, y as registerBehavior } from "./loader-
|
|
3
|
-
import {
|
|
2
|
+
import { m as diagnose, n as loadScene, y as registerBehavior } from "./loader-Buk8Bu1h.js";
|
|
3
|
+
import { h as Engine, m as AudioPlayer } from "./register-CscIzJEO.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
5
|
import { i as resolveRendering, n as attachTouchControls } from "./touch-BoNg_MnF.js";
|
|
6
6
|
import { a as poseFromRenderer, i as openBundledEditor, n as crossFade, r as devServerLibrary, t as teardown } from "./teardown-ByzfDPyu.js";
|
|
7
|
-
import { B as createCausticsQuad, F as PhysicsBody3D, R as Node3D, n as registerGameplayBehaviors } from "./gameplay-
|
|
7
|
+
import { B as createCausticsQuad, F as PhysicsBody3D, R as Node3D, n as registerGameplayBehaviors } from "./gameplay-BpQCbABv.js";
|
|
8
8
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
9
|
-
import { E as Camera3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets
|
|
10
|
-
import { n as enablePhysics3D } from "./physics-3d-
|
|
9
|
+
import { E as Camera3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-CQtEGogB.js";
|
|
10
|
+
import { n as enablePhysics3D } from "./physics-3d-DF8npb1O.js";
|
|
11
11
|
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";
|
|
12
12
|
import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
|
|
13
13
|
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -1566,6 +1566,7 @@ var Renderer3D = class {
|
|
|
1566
1566
|
preserveDrawingBuffer: rendering.preserveDrawingBuffer
|
|
1567
1567
|
});
|
|
1568
1568
|
this.webgl.info.autoReset = false;
|
|
1569
|
+
this.engine.picker = (x, y) => this.pick(x, y);
|
|
1569
1570
|
this.basePixelRatio = rendering.pixelRatio;
|
|
1570
1571
|
this.webgl.setPixelRatio(rendering.pixelRatio);
|
|
1571
1572
|
this.adaptive = opts.adaptiveResolution === false ? null : new AdaptiveResolution();
|
|
@@ -2082,6 +2083,7 @@ var Renderer3D = class {
|
|
|
2082
2083
|
this.webgl.shadowMap.needsUpdate = true;
|
|
2083
2084
|
}
|
|
2084
2085
|
dispose() {
|
|
2086
|
+
if (this.engine.picker) this.engine.picker = null;
|
|
2085
2087
|
this.disconnect();
|
|
2086
2088
|
this.threeScene.traverse((obj) => {
|
|
2087
2089
|
const mesh = obj;
|
|
@@ -2260,6 +2262,7 @@ async function createGame3D(opts) {
|
|
|
2260
2262
|
opts.onProgress?.(.16 + f * .82, "shaders");
|
|
2261
2263
|
});
|
|
2262
2264
|
} catch {}
|
|
2265
|
+
cleanups.push(engine.settings.bindAudio(engine.audio));
|
|
2263
2266
|
await report(1, "ready");
|
|
2264
2267
|
function disposeGame() {
|
|
2265
2268
|
teardown([
|
|
@@ -2280,6 +2283,9 @@ async function createGame3D(opts) {
|
|
|
2280
2283
|
assetErrors() {
|
|
2281
2284
|
return renderer.assets?.errors() ?? [];
|
|
2282
2285
|
},
|
|
2286
|
+
pick(x, y) {
|
|
2287
|
+
return engine.picker?.(x, y) ?? null;
|
|
2288
|
+
},
|
|
2283
2289
|
stats() {
|
|
2284
2290
|
return {
|
|
2285
2291
|
triangles: 0,
|
package/dist/debug.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as RendererStats,
|
|
1
|
+
import { C as RendererStats, lt as LogLevel, v as Engine } from "./behavior-CKwTCjfR.js";
|
|
2
2
|
|
|
3
3
|
//#region src/debug/panel.d.ts
|
|
4
4
|
/** Minimal document surface the overlay needs (injectable for tests). */
|
package/dist/editor.js
CHANGED
|
@@ -1075,6 +1075,41 @@ var dt = {
|
|
|
1075
1075
|
en: "Child of HudLayer. Set text/size/color/background; disabled greys it out. Emits the 'pressed' signal (behaviors: node.on('pressed', ...)); press() triggers it programmatically (gamepad menus, tests).",
|
|
1076
1076
|
ko: "HudLayer의 자식. text/size/color/background를 설정하고 disabled로 비활성화합니다. 'pressed' 시그널을 내며(비헤이비어에서 node.on('pressed', ...)), press()로 코드에서도 누를 수 있습니다(게임패드 메뉴, 테스트)."
|
|
1077
1077
|
}),
|
|
1078
|
+
F("UiPanel", {
|
|
1079
|
+
en: "A box that holds other widgets — the thing a menu, options screen or inventory actually is.",
|
|
1080
|
+
ko: "다른 위젯을 담는 상자 — 메뉴·설정 화면·인벤토리가 실제로 이것입니다."
|
|
1081
|
+
}, {
|
|
1082
|
+
en: "Child of HudLayer. Widgets under it mount INSIDE it, so tree structure becomes screen structure; panels nest. layout column|row|grid with columns (an inventory is a grid panel, one child per slot), plus gap/padding/background/radius/width/height/border. width or height 0 = size to the contents.",
|
|
1083
|
+
ko: "HudLayer의 자식. 그 아래 위젯들이 이 안에 마운트되어 트리 구조가 화면 구조가 됩니다(중첩 가능). layout은 column|row|grid이고 columns와 함께 씁니다(인벤토리 = grid 패널, 슬롯당 자식 하나). gap/padding/background/radius/width/height/border 지원. width·height가 0이면 내용에 맞춰집니다."
|
|
1084
|
+
}),
|
|
1085
|
+
F("UiImage", {
|
|
1086
|
+
en: "A picture in the HUD — item icons, portraits, a logo.",
|
|
1087
|
+
ko: "HUD 안의 그림 — 아이템 아이콘, 초상화, 로고."
|
|
1088
|
+
}, {
|
|
1089
|
+
en: "src takes a url or a $assetKey (declare the icon once like any other asset). fit contain|cover|fill; tint multiplies through the picture, which is how an unaffordable item greys out in one prop; opacity for disabled states.",
|
|
1090
|
+
ko: "src는 url 또는 $assetKey(아이콘도 다른 에셋처럼 한 번만 선언). fit은 contain|cover|fill, tint는 그림에 곱해져서 살 수 없는 아이템을 프롭 하나로 회색 처리합니다. opacity로 비활성 표현."
|
|
1091
|
+
}),
|
|
1092
|
+
F("UiSlider", {
|
|
1093
|
+
en: "A value the player sets — volume, sensitivity, difficulty.",
|
|
1094
|
+
ko: "플레이어가 조절하는 값 — 볼륨, 감도, 난이도."
|
|
1095
|
+
}, {
|
|
1096
|
+
en: "Emits changed(value). label/value/min/max/step/width/color. Setting .value from a behavior updates the control WITHOUT re-emitting, so restoring a saved setting does not fire the handler that saved it.",
|
|
1097
|
+
ko: "changed(value) 시그널. label/value/min/max/step/width/color. 비헤이비어에서 .value를 설정하면 컨트롤만 갱신되고 changed는 다시 발생하지 않습니다 — 저장된 설정을 복원할 때 저장 핸들러가 다시 도는 것을 막습니다."
|
|
1098
|
+
}),
|
|
1099
|
+
F("UiToggle", {
|
|
1100
|
+
en: "An on/off switch — mute, invert-Y, fullscreen.",
|
|
1101
|
+
ko: "켜기/끄기 스위치 — 음소거, Y축 반전, 전체화면."
|
|
1102
|
+
}, {
|
|
1103
|
+
en: "Emits changed(boolean). label/value. Same no-re-emit rule as UiSlider when set from code.",
|
|
1104
|
+
ko: "changed(boolean) 시그널. label/value. 코드에서 설정할 때 재발생하지 않는 규칙은 UiSlider와 같습니다."
|
|
1105
|
+
}),
|
|
1106
|
+
F("UiSelect", {
|
|
1107
|
+
en: "One of several — quality, resolution, language.",
|
|
1108
|
+
ko: "여러 개 중 하나 — 품질, 해상도, 언어."
|
|
1109
|
+
}, {
|
|
1110
|
+
en: "options is a comma-separated list (\"low,medium,high\"); value is the current one. Emits changed(value).",
|
|
1111
|
+
ko: "options는 쉼표로 구분된 목록(\"low,medium,high\"), value가 현재 선택입니다. changed(value) 시그널."
|
|
1112
|
+
}),
|
|
1078
1113
|
F("UiDialogue", {
|
|
1079
1114
|
en: "A typewriter dialogue box with a queue and choice buttons — the RPG conversation layer.",
|
|
1080
1115
|
ko: "타자기 효과·큐·선택지 버튼을 갖춘 대화창 — RPG 대화 레이어."
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { t as registerCoreNodes } from "./register-
|
|
1
|
+
import { t as registerCoreNodes } from "./register-CscIzJEO.js";
|
|
2
2
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
3
3
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
4
4
|
import { i as getNodeSchema, l as registerNode } from "./registry-CJdGpT2V.js";
|
|
5
5
|
import { t as createNoise2D } from "./noise-CGUMx44x.js";
|
|
6
6
|
import { i as applyParticlePreset, r as PARTICLE_PRESET_NAMES, t as ParticleSim } from "./particle-sim-Bw7hB93B.js";
|
|
7
|
-
import { A as Water3D, F as PhysicsBody3D, H as colliderFootDrop, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D } from "./gameplay-
|
|
7
|
+
import { A as Water3D, F as PhysicsBody3D, H as colliderFootDrop, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D } from "./gameplay-BpQCbABv.js";
|
|
8
8
|
import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
|
|
9
9
|
import { AdditiveBlending, AnimationClip, AnimationMixer, Box3, BoxGeometry, BufferAttribute, BufferGeometry, CanvasTexture, CapsuleGeometry, Color, ConeGeometry, CylinderGeometry, DataTexture, DirectionalLight, DoubleSide, DynamicDrawUsage, Euler, Group, IcosahedronGeometry, ImageBitmapLoader, InstancedBufferAttribute, InstancedMesh, LinearFilter, LoopOnce, LoopRepeat, Matrix4, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshPhysicalMaterial, MeshStandardMaterial, NearestFilter, NoBlending, NormalBlending, PerspectiveCamera, PlaneGeometry, PointLight, Points, PointsMaterial, Quaternion, QuaternionKeyframeTrack, RGBADepthPacking, RGBAFormat, RepeatWrapping, SRGBColorSpace, ShaderChunk, ShaderMaterial, SphereGeometry, Texture, TextureLoader, UniformsLib, UniformsUtils, Vector3, Vector4, VectorKeyframeTrack } from "three";
|
|
10
10
|
import { clone } from "three/addons/utils/SkeletonUtils.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { f as Node, g as Behavior, n as loadScene, y as registerBehavior } from "./loader-
|
|
1
|
+
import { f as Node, g as Behavior, n as loadScene, y as registerBehavior } from "./loader-Buk8Bu1h.js";
|
|
2
2
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
3
3
|
import { t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
4
|
-
import { r as effectiveOrder, t as duplicateNode } from "./duplicate-
|
|
4
|
+
import { r as effectiveOrder, t as duplicateNode } from "./duplicate-BgnG1Lqz.js";
|
|
5
5
|
import { Color, CubeCamera, DepthTexture, DoubleSide, Euler, FloatType, Frustum, HalfFloatType, LinearMipmapLinearFilter, MathUtils, Matrix4, Mesh, MeshDepthMaterial, Object3D, PerspectiveCamera, Plane, PlaneGeometry, Quaternion, ShaderMaterial, Sphere, Vector2, Vector3, Vector4, WebGLCubeRenderTarget, WebGLRenderTarget } from "three";
|
|
6
6
|
//#region src/3d/frustum.ts
|
|
7
7
|
const scratchFrustum = new Frustum();
|
|
@@ -4248,6 +4248,93 @@ var Chase = class extends Behavior {
|
|
|
4248
4248
|
}
|
|
4249
4249
|
};
|
|
4250
4250
|
//#endregion
|
|
4251
|
+
//#region src/gameplay/clickable.ts
|
|
4252
|
+
/**
|
|
4253
|
+
* Click and hover THIS node — the mouse as gameplay input.
|
|
4254
|
+
*
|
|
4255
|
+
* The raycast has always existed (`Renderer3D.pick` / `Renderer2D.pick`) and was
|
|
4256
|
+
* reachable only from whoever held the renderer, which a Behavior never does.
|
|
4257
|
+
* So every mouse-driven genre — match-3, tower defense, card and deckbuilder,
|
|
4258
|
+
* point-and-click, RTS, idle/clicker — had NO scene JSON to write. Not an
|
|
4259
|
+
* awkward API: none.
|
|
4260
|
+
*
|
|
4261
|
+
* ```json
|
|
4262
|
+
* { "name": "Tile", "type": "MeshInstance3D",
|
|
4263
|
+
* "script": { "name": "Clickable" } }
|
|
4264
|
+
* ```
|
|
4265
|
+
* ```json
|
|
4266
|
+
* "connections": [
|
|
4267
|
+
* { "from": "/Board/Tile", "signal": "clicked", "to": "/Board", "handler": "onTileClicked" }
|
|
4268
|
+
* ]
|
|
4269
|
+
* ```
|
|
4270
|
+
*
|
|
4271
|
+
* `clicked` fires on RELEASE over the same node the press started on — the
|
|
4272
|
+
* convention every button on every platform follows, so a drag that ends
|
|
4273
|
+
* elsewhere is not a click. `hovered`/`unhovered` bracket the cursor being over
|
|
4274
|
+
* it.
|
|
4275
|
+
*/
|
|
4276
|
+
var Clickable = class extends Behavior {
|
|
4277
|
+
static props = {
|
|
4278
|
+
/** Mouse button: 0 left, 1 middle, 2 right. */
|
|
4279
|
+
button: { default: 0 },
|
|
4280
|
+
/** Ignore clicks further away than this (0 = any distance). */
|
|
4281
|
+
maxDistance: { default: 0 },
|
|
4282
|
+
/** Stop responding without removing the behavior. */
|
|
4283
|
+
enabled: { default: true }
|
|
4284
|
+
};
|
|
4285
|
+
static signals = [
|
|
4286
|
+
"clicked",
|
|
4287
|
+
"hovered",
|
|
4288
|
+
"unhovered"
|
|
4289
|
+
];
|
|
4290
|
+
button = 0;
|
|
4291
|
+
maxDistance = 0;
|
|
4292
|
+
enabled = true;
|
|
4293
|
+
/** True while the cursor is over this node — read it to tint a hover state. */
|
|
4294
|
+
hovering = false;
|
|
4295
|
+
pressedHere = false;
|
|
4296
|
+
update() {
|
|
4297
|
+
const engine = this.node.tree?.engine;
|
|
4298
|
+
if (!engine || !this.enabled) return;
|
|
4299
|
+
const picker = engine.picker;
|
|
4300
|
+
const pointer = engine.input.pointerPosition();
|
|
4301
|
+
if (!picker || !pointer) {
|
|
4302
|
+
if (this.hovering) this.setHover(false);
|
|
4303
|
+
return;
|
|
4304
|
+
}
|
|
4305
|
+
const hit = picker(pointer.x, pointer.y);
|
|
4306
|
+
const over = hit !== null && this.isSelfOrDescendant(hit) && this.withinRange(hit);
|
|
4307
|
+
if (over !== this.hovering) this.setHover(over);
|
|
4308
|
+
if (engine.input.mouseJustPressed(this.button)) this.pressedHere = over;
|
|
4309
|
+
if (engine.input.mouseJustReleased(this.button)) {
|
|
4310
|
+
if (this.pressedHere && over) this.emit("clicked", this.node);
|
|
4311
|
+
this.pressedHere = false;
|
|
4312
|
+
}
|
|
4313
|
+
}
|
|
4314
|
+
setHover(next) {
|
|
4315
|
+
this.hovering = next;
|
|
4316
|
+
this.emit(next ? "hovered" : "unhovered", this.node);
|
|
4317
|
+
}
|
|
4318
|
+
/** A pick lands on the visual MESH, which is usually a child of the node. */
|
|
4319
|
+
isSelfOrDescendant(hit) {
|
|
4320
|
+
for (let n = hit; n; n = n.parent) if (n === this.node) return true;
|
|
4321
|
+
return false;
|
|
4322
|
+
}
|
|
4323
|
+
withinRange(hit) {
|
|
4324
|
+
if (this.maxDistance <= 0) return true;
|
|
4325
|
+
if (!this.node.tree?.engine?.scene?.root) return true;
|
|
4326
|
+
const a = this.node.position;
|
|
4327
|
+
const b = hit.position;
|
|
4328
|
+
if (!Array.isArray(a) || !Array.isArray(b)) return true;
|
|
4329
|
+
let sum = 0;
|
|
4330
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
4331
|
+
const d = (a[i] ?? 0) - (b[i] ?? 0);
|
|
4332
|
+
sum += d * d;
|
|
4333
|
+
}
|
|
4334
|
+
return Math.sqrt(sum) <= this.maxDistance;
|
|
4335
|
+
}
|
|
4336
|
+
};
|
|
4337
|
+
//#endregion
|
|
4251
4338
|
//#region src/gameplay/collector.ts
|
|
4252
4339
|
/**
|
|
4253
4340
|
* A tally for the "collect N things" pattern, living on the collector itself
|
|
@@ -6037,6 +6124,7 @@ const GAMEPLAY_BEHAVIORS = {
|
|
|
6037
6124
|
Collector,
|
|
6038
6125
|
DamageOnContact,
|
|
6039
6126
|
Interactable,
|
|
6127
|
+
Clickable,
|
|
6040
6128
|
FollowCamera,
|
|
6041
6129
|
Patrol,
|
|
6042
6130
|
Chase,
|
package/dist/gameplay.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { at as Node, l as PropSchema, n as BehaviorCtor, t as Behavior, v as Engine } from "./behavior-CKwTCjfR.js";
|
|
2
2
|
import { c as JsonValue, s as JsonObject } from "./schema-CcoWb32N.js";
|
|
3
3
|
|
|
4
4
|
//#region src/gameplay/chase.d.ts
|
package/dist/gameplay.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as FollowCamera, D as Health, E as DamageOnContact, O as Collector, S as restartScene, T as phaseOf, _ as hitStop, a as Wander, b as GameFlow, c as Projectile, d as PathFollow, f as Oscillate, g as Cooldown, h as CameraShake, i as WaveSpawner, k as Chase, l as Pickup, m as Lifetime, n as registerGameplayBehaviors, o as Spawner, p as MoveTo, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as Patrol, v as screenFlash, w as DayNight, x as goToScene, y as Interactable } from "./gameplay-
|
|
1
|
+
import { C as FollowCamera, D as Health, E as DamageOnContact, O as Collector, S as restartScene, T as phaseOf, _ as hitStop, a as Wander, b as GameFlow, c as Projectile, d as PathFollow, f as Oscillate, g as Cooldown, h as CameraShake, i as WaveSpawner, k as Chase, l as Pickup, m as Lifetime, n as registerGameplayBehaviors, o as Spawner, p as MoveTo, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as Patrol, v as screenFlash, w as DayNight, x as goToScene, y as Interactable } from "./gameplay-BpQCbABv.js";
|
|
2
2
|
export { CameraShake, Chase, Collector, Cooldown, DamageOnContact, DayNight, FollowCamera, GAMEPLAY_BEHAVIORS, GameFlow, Health, Interactable, Lifetime, MoveTo, Oscillate, PathFollow, Patrol, Pickup, Projectile, ScoreKeeper, Spawner, Wander, WaveSpawner, ZombieAI, goToScene, hitStop, phaseOf, registerGameplayBehaviors, restartScene, screenFlash };
|