incanto 0.32.0 → 0.34.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-CtPScDMo.d.ts} +149 -1
- package/dist/{create-game-bKHgHcsZ.js → create-game-CFNqoqOX.js} +13 -6
- package/dist/{create-game-gXI7PYl0.js → create-game-QTfghzwM.js} +11 -5
- package/dist/debug.d.ts +1 -1
- package/dist/{duplicate-KRPtUtzl.js → duplicate-DlOvknDO.js} +1 -1
- package/dist/editor.js +35 -0
- package/dist/{environment-presets--DigHNg4.js → environment-presets-B6WiUsaO.js} +2 -2
- package/dist/{gameplay-BftxM_It.js → gameplay-BxFtmfSe.js} +90 -2
- package/dist/gameplay.d.ts +1 -1
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +175 -23
- package/dist/index.js +5 -58
- package/dist/{loader-BlaRQGaA.js → loader-BwR0DxeM.js} +66 -0
- package/dist/{loader-BYBrqTxP.d.ts → loader-DmXfj6Uv.d.ts} +1 -1
- package/dist/net.d.ts +1 -1
- package/dist/net.js +3 -3
- package/dist/{pathfinding-BwhqPD3i.d.ts → pathfinding-DRCe89SI.d.ts} +1 -1
- package/dist/{physics-2d-D9wquBvK.js → physics-2d-BuyAwsW5.js} +12 -2
- package/dist/{physics-3d-CnPygVGo.js → physics-3d-C8Kn_Nyb.js} +55 -9
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-tkR_8tWg.js → register-BLPC10Mj.js} +145 -8
- package/dist/{register-Dzkd6-os.js → register-G3edsjJ2.js} +752 -16
- package/dist/{register-CUY284Is.js → register-OodmuUMK.js} +2 -2
- package/dist/{test-WwRIlXsK.js → test-C4B5znap.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-BTODHtdM.js} +1 -1
- package/editor/assets/{debug-BT_0mjk-.js → debug-CJEz4EwC.js} +1 -1
- package/editor/assets/{index-gfyrByWw.js → index-BYCso8Bf.js} +90 -90
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +667 -11
- package/skills/incanto-audio.md +43 -0
- package/skills/incanto-building-2d-games.md +36 -0
- package/skills/incanto-hud.md +97 -0
- package/skills/incanto-node-reference.md +131 -3
- 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/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-BxFtmfSe.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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as MusicBackend, A as suggestQuality, B as Listener, C as RendererStats, D as SettingsValues, E as Settings, F as SfxEngine, G as spatialGain, H as RolloffModel, I as SfxPlayOptions, J as SFX_PRESET_NAMES, K as spatialPan, L as isAudioContextAvailable, M as createSaveStore, N as Scene, O as qualityEnvironment, P as InputMap, Q as synthSfx, R as Voice, S as GameStats, T as QualityTier, U as SpatialParams, V as ROLLOFF_MODELS, W as Vec3, X as SfxWave, Y as SfxParams, Z as SynthOptions, _ as registeredTypes, a as registerBehavior, at as Node, b as Scheduler, c as PropDef, ct as LogEntry, d as createNode, dt as Signal, et as MusicManager, f as getNodeSchema, ft as SignalListener, g as registerNode, h as mergeStaticSignals, i as getBehavior, it as BusName, j as SaveStore, k as readDeviceHints, l as PropSchema, lt as LogLevel, m as getNodeType, n as BehaviorCtor, nt as PlayMusicOptions, o as registeredBehaviors, ot as NodeLifecycle, p as getNodeSignals, q as SFX_PRESETS, r as clearBehaviors, rt as AudioBuses, s as NodeCtor, st as SceneTree, t as Behavior, tt as MusicTrack, u as clearRegistry, ut as LogManager, v as Engine, w as DeviceHints, x as EngineStats, y as EngineOptions, z as VoicePreset } from "./behavior-CtPScDMo.js";
|
|
2
2
|
import { a as Rng, c as JsonValue, d as jsonKind, i as SceneJson, l as jsonClone, n as NodeJson, o as JsonKind, r as SCENE_FORMAT, s as JsonObject, t as ConnectionJson, u as jsonEquals } from "./schema-CcoWb32N.js";
|
|
3
|
-
import { n as loadScene, t as LoadSceneOptions } from "./loader-
|
|
3
|
+
import { n as loadScene, t as LoadSceneOptions } from "./loader-DmXfj6Uv.js";
|
|
4
4
|
import { n as ParticleSimConfig, r as ParticleView, t as ParticleSim } from "./particle-sim-CwJ5rI_P.js";
|
|
5
|
-
import { a as AudioElementLike, i as gridFromRows, n as PathGrid, o as AudioPlayer, r as findPath, t as FindPathOptions } from "./pathfinding-
|
|
5
|
+
import { a as AudioElementLike, i as gridFromRows, n as PathGrid, o as AudioPlayer, r as findPath, t as FindPathOptions } from "./pathfinding-DRCe89SI.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
|
|
@@ -120,6 +120,7 @@ declare class HudLayer extends Node {
|
|
|
120
120
|
static readonly props: PropSchema;
|
|
121
121
|
zIndex: number;
|
|
122
122
|
visible: boolean;
|
|
123
|
+
focusNavigation: boolean;
|
|
123
124
|
/** @internal root overlay element (null headless). */
|
|
124
125
|
_element: HTMLElement | null;
|
|
125
126
|
private readonly slots;
|
|
@@ -138,19 +139,68 @@ declare class HudLayer extends Node {
|
|
|
138
139
|
private _mount;
|
|
139
140
|
override onExitTree(): void;
|
|
140
141
|
override update(): void;
|
|
142
|
+
/**
|
|
143
|
+
* Arrow keys / d-pad move the focus, Enter / A activates it.
|
|
144
|
+
*
|
|
145
|
+
* Off by default: a game whose HUD has a button must not lose its arrow keys
|
|
146
|
+
* to a menu the moment one exists. Turn it on for the screens that ARE menus
|
|
147
|
+
* (`"focusNavigation": true` on the pause panel's layer), and off again when
|
|
148
|
+
* play resumes.
|
|
149
|
+
*/
|
|
150
|
+
private stepFocus;
|
|
151
|
+
/** Focusable widgets under this layer, in tree order. */
|
|
152
|
+
private focusables;
|
|
153
|
+
/** Move focus to a widget by hand — opening a menu should start somewhere. */
|
|
154
|
+
focus(widget: HudWidgetBase | null): void;
|
|
141
155
|
/** @internal Widgets mount into per-anchor flex columns. */
|
|
142
156
|
_slot(anchor: HudAnchor): HTMLElement | null;
|
|
143
157
|
}
|
|
144
158
|
/** Shared plumbing: mount into the parent HudLayer's anchor slot. */
|
|
145
159
|
declare abstract class HudWidgetBase extends Node {
|
|
146
160
|
static readonly props: PropSchema;
|
|
161
|
+
static readonly signals: readonly string[];
|
|
147
162
|
anchor: HudAnchor;
|
|
148
163
|
visible: boolean;
|
|
164
|
+
focusable: boolean;
|
|
165
|
+
draggable: boolean;
|
|
166
|
+
dropTarget: boolean;
|
|
167
|
+
/** @internal Set by the owning HudLayer while this widget has focus. */
|
|
168
|
+
_focused: boolean;
|
|
169
|
+
/**
|
|
170
|
+
* @internal Confirm (`dir` 0) or nudge (-1 left / +1 right) — what pressing
|
|
171
|
+
* A or an arrow ON this widget means. Default: nothing.
|
|
172
|
+
*/
|
|
173
|
+
_activate(_dir: number): void;
|
|
174
|
+
/** @internal Draw the focus ring. Overridable if a widget wants its own. */
|
|
175
|
+
_paintFocus(): void;
|
|
149
176
|
/** @internal */
|
|
150
177
|
_element: HTMLElement | null;
|
|
151
178
|
protected abstract _build(): HTMLElement;
|
|
152
179
|
private layer;
|
|
153
180
|
override onReady(): void;
|
|
181
|
+
/**
|
|
182
|
+
* @internal Build and attach, once a host exists.
|
|
183
|
+
*
|
|
184
|
+
* A widget inside a UiPanel mounts into the PANEL, not the layer's anchor
|
|
185
|
+
* slot — that is what turns structure in the tree into structure on screen,
|
|
186
|
+
* and it is what a menu is. Ready order does not decide it: the panel builds
|
|
187
|
+
* on demand when a child asks (`_container`), and `update` retries for
|
|
188
|
+
* anything attached at runtime before its host existed.
|
|
189
|
+
*/
|
|
190
|
+
_mountWidget(): void;
|
|
191
|
+
/**
|
|
192
|
+
* Drag and drop, on the DOM the engine already builds.
|
|
193
|
+
*
|
|
194
|
+
* An inventory is the one screen where "click it" is not enough, and every
|
|
195
|
+
* game that wanted one dropped out of scene JSON to hand-roll pointer
|
|
196
|
+
* handlers. The whole gesture is four signals and no new node type: a
|
|
197
|
+
* `draggable` widget emits `dragStarted` and, if it lands on one,
|
|
198
|
+
* `droppedOn(target)`; a `dropTarget` emits `dropped(source)`. Who owns the
|
|
199
|
+
* ITEM is the game's business — this reports the gesture, not a model.
|
|
200
|
+
*/
|
|
201
|
+
private _wireDrag;
|
|
202
|
+
/** The nearest ancestor that holds widgets itself (a UiPanel). */
|
|
203
|
+
private host;
|
|
154
204
|
override onExitTree(): void;
|
|
155
205
|
override update(_dt: number): void;
|
|
156
206
|
protected _sync(): void;
|
|
@@ -232,6 +282,9 @@ declare class UiButton extends HudWidgetBase {
|
|
|
232
282
|
color: string;
|
|
233
283
|
background: string;
|
|
234
284
|
disabled: boolean;
|
|
285
|
+
override focusable: boolean;
|
|
286
|
+
/** Enter / A on a focused button is a press. */
|
|
287
|
+
override _activate(_dir: number): void;
|
|
235
288
|
private lastText;
|
|
236
289
|
/** Programmatic press — same path as a click (tests, gamepad menus). */
|
|
237
290
|
press(): void;
|
|
@@ -305,6 +358,124 @@ declare class Timer extends Node {
|
|
|
305
358
|
override update(dt: number): void;
|
|
306
359
|
}
|
|
307
360
|
//#endregion
|
|
361
|
+
//#region src/core/nodes/ui-kit.d.ts
|
|
362
|
+
/**
|
|
363
|
+
* A box that holds other widgets — the thing a menu actually is.
|
|
364
|
+
*
|
|
365
|
+
* Widgets normally mount into their HudLayer's anchor slot, which is why a
|
|
366
|
+
* "menu" used to be a flat pile of anchored items with no way to sit them in a
|
|
367
|
+
* panel, space them, or lay them out in a grid. A `UiPanel` becomes the parent
|
|
368
|
+
* for every widget under it, so structure in the TREE is structure on SCREEN.
|
|
369
|
+
*
|
|
370
|
+
* ```json
|
|
371
|
+
* { "name": "Pause", "type": "UiPanel", "props": { "anchor": "center", "layout": "column", "gap": 12 },
|
|
372
|
+
* "children": [
|
|
373
|
+
* { "name": "Title", "type": "UiText", "props": { "text": "PAUSED", "size": 28 } },
|
|
374
|
+
* { "name": "Resume", "type": "UiButton", "props": { "label": "Resume" } }
|
|
375
|
+
* ] }
|
|
376
|
+
* ```
|
|
377
|
+
*/
|
|
378
|
+
declare class UiPanel extends HudWidgetBase {
|
|
379
|
+
static override readonly typeName: string;
|
|
380
|
+
static override readonly props: PropSchema;
|
|
381
|
+
layout: "column" | "row" | "grid";
|
|
382
|
+
columns: number;
|
|
383
|
+
gap: number;
|
|
384
|
+
padding: number;
|
|
385
|
+
background: string;
|
|
386
|
+
radius: number;
|
|
387
|
+
width: number;
|
|
388
|
+
height: number;
|
|
389
|
+
border: string;
|
|
390
|
+
private lastKey;
|
|
391
|
+
protected _build(): HTMLElement;
|
|
392
|
+
/**
|
|
393
|
+
* @internal Children mount HERE, not in the layer's anchor slot.
|
|
394
|
+
*
|
|
395
|
+
* Builds on demand: a child asking for its host must not depend on whose
|
|
396
|
+
* `onReady` the tree happened to run first.
|
|
397
|
+
*/
|
|
398
|
+
_container(): HTMLElement | null;
|
|
399
|
+
private css;
|
|
400
|
+
protected override _sync(): void;
|
|
401
|
+
}
|
|
402
|
+
/** A picture: an item icon, a portrait, a logo. `src` takes a url or `$assetKey`. */
|
|
403
|
+
declare class UiImage extends HudWidgetBase {
|
|
404
|
+
static override readonly typeName: string;
|
|
405
|
+
static override readonly props: PropSchema;
|
|
406
|
+
src: string;
|
|
407
|
+
width: number;
|
|
408
|
+
height: number;
|
|
409
|
+
fit: "contain" | "cover" | "fill";
|
|
410
|
+
tint: string;
|
|
411
|
+
opacity: number;
|
|
412
|
+
private last;
|
|
413
|
+
protected _build(): HTMLElement;
|
|
414
|
+
private resolved;
|
|
415
|
+
private key;
|
|
416
|
+
private css;
|
|
417
|
+
protected override _sync(): void;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* A value the player sets — volume, sensitivity, difficulty.
|
|
421
|
+
*
|
|
422
|
+
* Emits `changed(value)`. `incanto-audio.md` promised "a settings slider needs
|
|
423
|
+
* no extra wiring" while no slider existed; this is that slider.
|
|
424
|
+
*/
|
|
425
|
+
declare class UiSlider extends HudWidgetBase {
|
|
426
|
+
static override readonly typeName: string;
|
|
427
|
+
static override readonly props: PropSchema;
|
|
428
|
+
static override readonly signals: readonly string[];
|
|
429
|
+
label: string;
|
|
430
|
+
value: number;
|
|
431
|
+
min: number;
|
|
432
|
+
max: number;
|
|
433
|
+
step: number;
|
|
434
|
+
width: number;
|
|
435
|
+
color: string;
|
|
436
|
+
override focusable: boolean;
|
|
437
|
+
/** Left/right nudge by one step — the only sane thing a d-pad can mean here. */
|
|
438
|
+
override _activate(dir: number): void;
|
|
439
|
+
private input;
|
|
440
|
+
private text;
|
|
441
|
+
private last;
|
|
442
|
+
protected _build(): HTMLElement;
|
|
443
|
+
protected override _sync(): void;
|
|
444
|
+
}
|
|
445
|
+
/** An on/off switch — mute, invert-Y, fullscreen. Emits `changed(boolean)`. */
|
|
446
|
+
declare class UiToggle extends HudWidgetBase {
|
|
447
|
+
static override readonly typeName: string;
|
|
448
|
+
static override readonly props: PropSchema;
|
|
449
|
+
static override readonly signals: readonly string[];
|
|
450
|
+
label: string;
|
|
451
|
+
value: boolean;
|
|
452
|
+
override focusable: boolean;
|
|
453
|
+
/** Confirm flips it; left/right set it explicitly, which reads better on a pad. */
|
|
454
|
+
override _activate(dir: number): void;
|
|
455
|
+
private input;
|
|
456
|
+
private last;
|
|
457
|
+
protected _build(): HTMLElement;
|
|
458
|
+
protected override _sync(): void;
|
|
459
|
+
}
|
|
460
|
+
/** One of several — quality, resolution, language. Emits `changed(value)`. */
|
|
461
|
+
declare class UiSelect extends HudWidgetBase {
|
|
462
|
+
static override readonly typeName: string;
|
|
463
|
+
static override readonly props: PropSchema;
|
|
464
|
+
static override readonly signals: readonly string[];
|
|
465
|
+
label: string;
|
|
466
|
+
options: string;
|
|
467
|
+
value: string;
|
|
468
|
+
override focusable: boolean;
|
|
469
|
+
/** Left/right (and confirm) walk the list — a select has no other gesture. */
|
|
470
|
+
override _activate(dir: number): void;
|
|
471
|
+
private select;
|
|
472
|
+
private lastOptions;
|
|
473
|
+
private last;
|
|
474
|
+
protected _build(): HTMLElement;
|
|
475
|
+
private fillOptions;
|
|
476
|
+
protected override _sync(): void;
|
|
477
|
+
}
|
|
478
|
+
//#endregion
|
|
308
479
|
//#region src/core/noise.d.ts
|
|
309
480
|
/**
|
|
310
481
|
* Seeded 2D simplex noise (Ken Perlin's simplex, Gustavson's reference
|
|
@@ -463,25 +634,6 @@ declare function replay(engine: Engine, recording: ReplayJson, opts?: {
|
|
|
463
634
|
onTick?: (index: number) => void;
|
|
464
635
|
}): void;
|
|
465
636
|
//#endregion
|
|
466
|
-
//#region src/core/save.d.ts
|
|
467
|
-
/**
|
|
468
|
-
* Namespaced game persistence — high scores, unlocks, settings. localStorage
|
|
469
|
-
* in the browser, in-memory headless (tests and SSR stay green). Values are
|
|
470
|
-
* JSON round-tripped, so what you get back is what you saved.
|
|
471
|
-
*
|
|
472
|
-
* const save = createSaveStore('my-game');
|
|
473
|
-
* save.set('highScore', 4200);
|
|
474
|
-
* const best = save.get('highScore', 0);
|
|
475
|
-
*/
|
|
476
|
-
interface SaveStore {
|
|
477
|
-
get<T extends JsonValue>(key: string, fallback: T): T;
|
|
478
|
-
set(key: string, value: JsonValue): void;
|
|
479
|
-
remove(key: string): void;
|
|
480
|
-
/** Wipe THIS namespace only. */
|
|
481
|
-
clear(): void;
|
|
482
|
-
}
|
|
483
|
-
declare function createSaveStore(namespace: string): SaveStore;
|
|
484
|
-
//#endregion
|
|
485
637
|
//#region src/core/scene/constants.d.ts
|
|
486
638
|
/** The single reserved key marking a prop value as a constant reference. */
|
|
487
639
|
declare const CONST_REF_KEY = "@const";
|
|
@@ -606,4 +758,4 @@ declare function computeViewport(canvasW: number, canvasH: number, viewport: {
|
|
|
606
758
|
/** Engine version. Kept in sync with package.json by the release pipeline. */
|
|
607
759
|
declare const VERSION: string;
|
|
608
760
|
//#endregion
|
|
609
|
-
export { AudioBuses, type AudioElementLike, AudioPlayer, Behavior, type BehaviorCtor, type BusName, CONST_REF_KEY, type ComputedViewport, type ConnectionJson, type CrossfadeGains, type DebugLineSource, Engine, type EngineOptions, type EngineStats, type FindPathOptions, type GameStats, type HudAnchor, HudLayer, IncantoError, type IncantoErrorCode, type IncantoErrorDetails, InputMap, type JsonKind, type JsonObject, type JsonValue, type Listener, type LoadSceneOptions, type LogEntry, type LogLevel, LogManager, type MusicBackend, MusicManager, type MusicTrack, Node, type NodeCtor, type NodeJson, type NodeLifecycle, ORDER_GROUP_BASE, type OrderGroup, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, type ParsedNodePath, type ParticlePresetValues, ParticleSim, type ParticleSimConfig, type ParticleView, type PathGrid, type PlayMusicOptions, type PreloadResult, type PropDef, type PropSchema, ROLLOFF_MODELS, type Recorder, type RendererStats, type ReplayEvent, type ReplayJson, type ResolvedRendering, type ResolvedViewport, Rng, type RolloffModel, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, type SaveStore, Scene, type SceneJson, SceneTree, type Scheduler, SfxEngine, type SfxParams, type SfxPlayOptions, type SfxWave, Signal, type SignalListener, type SpatialParams, type SynthOptions, Timer, TouchControls, type TouchControlsOptions, UiBanner, UiBar, UiButton, UiDialogue, UiText, VERSION, type Vec3, type ViewportFit, type Voice, type VoicePreset, 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 };
|
|
761
|
+
export { AudioBuses, type AudioElementLike, AudioPlayer, Behavior, type BehaviorCtor, type BusName, CONST_REF_KEY, type ComputedViewport, type ConnectionJson, type CrossfadeGains, type DebugLineSource, type DeviceHints, Engine, type EngineOptions, type EngineStats, type FindPathOptions, type GameStats, type HudAnchor, HudLayer, IncantoError, type IncantoErrorCode, type IncantoErrorDetails, InputMap, type JsonKind, type JsonObject, type JsonValue, type Listener, type LoadSceneOptions, type LogEntry, type LogLevel, LogManager, type MusicBackend, MusicManager, type MusicTrack, Node, type NodeCtor, type NodeJson, type NodeLifecycle, ORDER_GROUP_BASE, type OrderGroup, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, type ParsedNodePath, type ParticlePresetValues, ParticleSim, type ParticleSimConfig, type ParticleView, type PathGrid, type PlayMusicOptions, type PreloadResult, type PropDef, type PropSchema, type QualityTier, ROLLOFF_MODELS, type Recorder, type RendererStats, type ReplayEvent, type ReplayJson, type ResolvedRendering, type ResolvedViewport, Rng, type RolloffModel, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, type SaveStore, Scene, type SceneJson, SceneTree, type Scheduler, Settings, type SettingsValues, SfxEngine, type SfxParams, type SfxPlayOptions, type SfxWave, Signal, type SignalListener, type SpatialParams, type SynthOptions, Timer, TouchControls, type TouchControlsOptions, UiBanner, UiBar, UiButton, UiDialogue, UiImage, UiPanel, UiSelect, UiSlider, UiText, UiToggle, VERSION, type Vec3, type ViewportFit, type Voice, type VoicePreset, 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, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveConstants, resolveRendering, resolveViewport, serializeNode, spatialGain, spatialPan, startRecording, suggestQuality, synthSfx };
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { _ as clearBehaviors, a as SCENE_FORMAT, b as registeredBehaviors, c as SceneTree, d as resolveConstants, f as Node, g as Behavior, h as InputMap, i as serializeNode, l as CONST_REF_KEY, n as loadScene, o as computeViewport, p as parseNodePath, r as Scene, s as resolveViewport, u as isConstRef, v as getBehavior, x as Signal, y as registerBehavior } from "./loader-
|
|
2
|
-
import { C as fadeGain, S as
|
|
1
|
+
import { _ as clearBehaviors, a as SCENE_FORMAT, b as registeredBehaviors, c as SceneTree, d as resolveConstants, f as Node, g as Behavior, h as InputMap, i as serializeNode, l as CONST_REF_KEY, n as loadScene, o as computeViewport, p as parseNodePath, r as Scene, s as resolveViewport, u as isConstRef, v as getBehavior, x as Signal, y as registerBehavior } from "./loader-BwR0DxeM.js";
|
|
2
|
+
import { A as MusicManager, C as isAudioContextAvailable, D as SFX_PRESETS, E as spatialPan, M as crossfadeGains, N as fadeGain, O as SFX_PRESET_NAMES, P as AudioBuses, S as SfxEngine, T as spatialGain, _ as qualityEnvironment, a as UiSlider, b as createSaveStore, c as UiButton, d as UiBanner, f as UiBar, g as Settings, h as Engine, i as UiSelect, j as WebAudioMusicBackend, k as synthSfx, l as UiDialogue, m as AudioPlayer, n as UiImage, o as UiToggle, p as UiText, r as UiPanel, s as Timer, t as registerCoreNodes, u as HudLayer, v as readDeviceHints, w as ROLLOFF_MODELS, x as LogManager, y as suggestQuality } from "./register-G3edsjJ2.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
5
5
|
import { t as auditScene } from "./audit-C4kmDK0o.js";
|
|
6
6
|
import { n as jsonEquals, r as jsonKind, t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
7
7
|
import { a as getNodeSignals, c as mergeStaticSignals, i as getNodeSchema, l as registerNode, n as clearRegistry, o as getNodeType, r as createNode, u as registeredTypes } from "./registry-CJdGpT2V.js";
|
|
8
8
|
import { t as createNoise2D } from "./noise-CGUMx44x.js";
|
|
9
|
-
import { n as ORDER_GROUP_BASE, r as effectiveOrder, t as duplicateNode } from "./duplicate-
|
|
9
|
+
import { n as ORDER_GROUP_BASE, r as effectiveOrder, t as duplicateNode } from "./duplicate-DlOvknDO.js";
|
|
10
10
|
import { i as applyParticlePreset, n as PARTICLE_PRESETS, r as PARTICLE_PRESET_NAMES, t as ParticleSim } from "./particle-sim-Bw7hB93B.js";
|
|
11
11
|
import { i as resolveRendering, n as attachTouchControls, r as joystickVector, t as TouchControls } from "./touch-BoNg_MnF.js";
|
|
12
12
|
//#region src/core/pathfinding.ts
|
|
@@ -225,59 +225,6 @@ function replay(engine, recording, opts) {
|
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
//#endregion
|
|
228
|
-
//#region src/core/save.ts
|
|
229
|
-
const memoryStores = /* @__PURE__ */ new Map();
|
|
230
|
-
function createSaveStore(namespace) {
|
|
231
|
-
const prefix = `incanto:${namespace}:`;
|
|
232
|
-
const local = storageOrNull();
|
|
233
|
-
if (!local) {
|
|
234
|
-
let mem = memoryStores.get(namespace);
|
|
235
|
-
if (!mem) {
|
|
236
|
-
mem = /* @__PURE__ */ new Map();
|
|
237
|
-
memoryStores.set(namespace, mem);
|
|
238
|
-
}
|
|
239
|
-
const backing = mem;
|
|
240
|
-
return {
|
|
241
|
-
get: (key, fallback) => parse(backing.get(key), fallback),
|
|
242
|
-
set: (key, value) => void backing.set(key, JSON.stringify(value)),
|
|
243
|
-
remove: (key) => void backing.delete(key),
|
|
244
|
-
clear: () => backing.clear()
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
return {
|
|
248
|
-
get: (key, fallback) => parse(local.getItem(prefix + key) ?? void 0, fallback),
|
|
249
|
-
set: (key, value) => local.setItem(prefix + key, JSON.stringify(value)),
|
|
250
|
-
remove: (key) => local.removeItem(prefix + key),
|
|
251
|
-
clear: () => {
|
|
252
|
-
const doomed = [];
|
|
253
|
-
for (let i = 0; i < local.length; i++) {
|
|
254
|
-
const k = local.key(i);
|
|
255
|
-
if (k?.startsWith(prefix)) doomed.push(k);
|
|
256
|
-
}
|
|
257
|
-
for (const k of doomed) local.removeItem(k);
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
function parse(raw, fallback) {
|
|
262
|
-
if (raw === void 0 || raw === null) return fallback;
|
|
263
|
-
try {
|
|
264
|
-
return JSON.parse(raw);
|
|
265
|
-
} catch {
|
|
266
|
-
return fallback;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
function storageOrNull() {
|
|
270
|
-
try {
|
|
271
|
-
if (typeof localStorage === "undefined") return null;
|
|
272
|
-
const probe = "__incanto_probe__";
|
|
273
|
-
localStorage.setItem(probe, "1");
|
|
274
|
-
localStorage.removeItem(probe);
|
|
275
|
-
return localStorage;
|
|
276
|
-
} catch {
|
|
277
|
-
return null;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
//#endregion
|
|
281
228
|
//#region src/core/uid-gen.ts
|
|
282
229
|
/**
|
|
283
230
|
* The ONE way to mint a node uid: crypto-strength, `n_` + 16 base36 chars
|
|
@@ -295,6 +242,6 @@ function newUid() {
|
|
|
295
242
|
//#endregion
|
|
296
243
|
//#region src/index.ts
|
|
297
244
|
/** Engine version. Kept in sync with package.json by the release pipeline. */
|
|
298
|
-
const VERSION = "0.
|
|
245
|
+
const VERSION = "0.34.0";
|
|
299
246
|
//#endregion
|
|
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 };
|
|
247
|
+
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, Settings, SfxEngine, Signal, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiImage, UiPanel, UiSelect, UiSlider, UiText, UiToggle, 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, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveConstants, resolveRendering, resolveViewport, serializeNode, spatialGain, spatialPan, startRecording, suggestQuality, synthSfx };
|
|
@@ -141,6 +141,40 @@ var InputMap = class {
|
|
|
141
141
|
declare(decls) {
|
|
142
142
|
for (const [name, action] of parseInputDecls(decls)) this.actions.set(name, action);
|
|
143
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Where the pointer is, in CANVAS pixels (top-left origin), or null when it
|
|
146
|
+
* has never been over the canvas.
|
|
147
|
+
*
|
|
148
|
+
* This is what a click-driven game asks for. `pointerDelta()` answers "how far
|
|
149
|
+
* did the mouse move" — the mouse-look question — and for a whole class of
|
|
150
|
+
* genres that is the wrong question and the only one the engine could answer.
|
|
151
|
+
* Pair it with `renderer.pick(x, y)` to get the node under the cursor.
|
|
152
|
+
*/
|
|
153
|
+
pointerPosition() {
|
|
154
|
+
return this.pointerPos ? { ...this.pointerPos } : null;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* @internal Feed a pointer position. `target` scales client → canvas pixels
|
|
158
|
+
* so a CSS-stretched canvas still reports coordinates its renderer can use.
|
|
159
|
+
*/
|
|
160
|
+
setPointerPosition(clientX, clientY, target) {
|
|
161
|
+
const rect = target?.getBoundingClientRect?.();
|
|
162
|
+
if (!rect || rect.width === 0 || rect.height === 0) {
|
|
163
|
+
this.pointerPos = {
|
|
164
|
+
x: clientX,
|
|
165
|
+
y: clientY
|
|
166
|
+
};
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const el = target;
|
|
170
|
+
const scaleX = typeof el.width === "number" && el.width > 0 ? el.width / rect.width : 1;
|
|
171
|
+
const scaleY = typeof el.height === "number" && el.height > 0 ? el.height / rect.height : 1;
|
|
172
|
+
this.pointerPos = {
|
|
173
|
+
x: (clientX - rect.left) * scaleX,
|
|
174
|
+
y: (clientY - rect.top) * scaleY
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
pointerPos = null;
|
|
144
178
|
/** Feed a key state change (code = KeyboardEvent.code, e.g. 'Space', 'KeyW'). */
|
|
145
179
|
handleKey(code, isDown) {
|
|
146
180
|
if (isDown) {
|
|
@@ -318,6 +352,7 @@ var InputMap = class {
|
|
|
318
352
|
let buttonsHeld = 0;
|
|
319
353
|
const onDown = (e) => {
|
|
320
354
|
buttonsHeld++;
|
|
355
|
+
this.setPointerPosition(e.clientX, e.clientY, target);
|
|
321
356
|
this.handleMouseButton(e.button, true);
|
|
322
357
|
if (opts?.lockOnClick && document.pointerLockElement !== target) target.requestPointerLock?.();
|
|
323
358
|
};
|
|
@@ -326,6 +361,7 @@ var InputMap = class {
|
|
|
326
361
|
this.handleMouseButton(e.button, false);
|
|
327
362
|
};
|
|
328
363
|
const onMove = (e) => {
|
|
364
|
+
this.setPointerPosition(e.clientX, e.clientY, target);
|
|
329
365
|
if (document.pointerLockElement === target || buttonsHeld > 0) this.handlePointerMove(e.movementX, e.movementY);
|
|
330
366
|
};
|
|
331
367
|
const onWheel = (e) => {
|
|
@@ -409,6 +445,36 @@ var InputMap = class {
|
|
|
409
445
|
justReleased(action) {
|
|
410
446
|
return this.button(action).keys.some((k) => this.releasedEdge.has(k)) || this.injectedReleased.has(action);
|
|
411
447
|
}
|
|
448
|
+
/**
|
|
449
|
+
* Mouse button state WITHOUT declaring an action for it.
|
|
450
|
+
*
|
|
451
|
+
* A click on a tile is not a bindable action — there is no key to remap, and
|
|
452
|
+
* asking a match-3 to declare `"click": { "keys": ["Mouse0"] }` in every scene
|
|
453
|
+
* is ceremony. Buttons already live in the key set as `Mouse0`/`Mouse1`/…;
|
|
454
|
+
* these read them directly. 0 left, 1 middle, 2 right.
|
|
455
|
+
*/
|
|
456
|
+
/**
|
|
457
|
+
* Is this raw CODE down / just pressed? (`'ArrowUp'`, `'Enter'`, `'Pad12'`…)
|
|
458
|
+
*
|
|
459
|
+
* Menu navigation is not a bindable action — there is no key to remap, and
|
|
460
|
+
* asking every scene to declare `"menuUp": { "keys": ["ArrowUp", "Pad12"] }`
|
|
461
|
+
* is ceremony for something every menu on every platform does the same way.
|
|
462
|
+
*/
|
|
463
|
+
keyPressed(code) {
|
|
464
|
+
return this.down.has(code);
|
|
465
|
+
}
|
|
466
|
+
keyJustPressed(code) {
|
|
467
|
+
return this.pressedEdge.has(code);
|
|
468
|
+
}
|
|
469
|
+
mousePressed(button = 0) {
|
|
470
|
+
return this.down.has(`Mouse${button}`);
|
|
471
|
+
}
|
|
472
|
+
mouseJustPressed(button = 0) {
|
|
473
|
+
return this.pressedEdge.has(`Mouse${button}`);
|
|
474
|
+
}
|
|
475
|
+
mouseJustReleased(button = 0) {
|
|
476
|
+
return this.releasedEdge.has(`Mouse${button}`);
|
|
477
|
+
}
|
|
412
478
|
/** Normalized direction for a vector2 action (y-down: up = -y). */
|
|
413
479
|
getVector(action) {
|
|
414
480
|
const def = this.get(action);
|
package/dist/net.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { at as Node, dt as Signal, l as PropSchema, v as Engine } from "./behavior-CtPScDMo.js";
|
|
2
2
|
import { c as JsonValue, i as SceneJson, s as JsonObject } from "./schema-CcoWb32N.js";
|
|
3
3
|
|
|
4
4
|
//#region src/net/types.d.ts
|
package/dist/net.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { n as loadScene } from "./loader-
|
|
2
|
-
import {
|
|
1
|
+
import { n as loadScene } from "./loader-BwR0DxeM.js";
|
|
2
|
+
import { h as Engine } from "./register-G3edsjJ2.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
5
5
|
import { n as createAgent8Server } from "./agent8-CvsfVskX.js";
|
|
6
|
-
import { i as applySyncPatch, n as NetworkSpawner, r as NetworkManager, t as registerNodesNet } from "./register-
|
|
6
|
+
import { i as applySyncPatch, n as NetworkSpawner, r as NetworkManager, t as registerNodesNet } from "./register-OodmuUMK.js";
|
|
7
7
|
//#region src/net/loopback.ts
|
|
8
8
|
/**
|
|
9
9
|
* In-memory multiplayer hub implementing the SAME kernel contract as
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { m as diagnose } from "./loader-
|
|
2
|
+
import { m as diagnose } from "./loader-BwR0DxeM.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
|
-
import { _ as RigidBody2D, b as validateCollider2D, g as PhysicsBody2D, h as CharacterBody2D, m as Area2D, p as Joint2D, y as Node2D } from "./register-
|
|
4
|
+
import { _ as RigidBody2D, b as validateCollider2D, g as PhysicsBody2D, h as CharacterBody2D, m as Area2D, p as Joint2D, y as Node2D } from "./register-BLPC10Mj.js";
|
|
5
5
|
import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
|
|
6
6
|
//#region src/2d/physics/physics-2d.ts
|
|
7
7
|
var physics_2d_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -153,6 +153,16 @@ var Physics2D = class {
|
|
|
153
153
|
y: t.y + corrected.y
|
|
154
154
|
});
|
|
155
155
|
node._grounded = this.kcc.computedGrounded();
|
|
156
|
+
node._onWall = 0;
|
|
157
|
+
node._onCeiling = false;
|
|
158
|
+
const hits = this.kcc.numComputedCollisions();
|
|
159
|
+
for (let i = 0; i < hits; i++) {
|
|
160
|
+
const n = this.kcc.computedCollision(i)?.normal1;
|
|
161
|
+
if (!n) continue;
|
|
162
|
+
if (Math.abs(n.y) > .7) {
|
|
163
|
+
if (!node._grounded) node._onCeiling = true;
|
|
164
|
+
} else if (Math.abs(n.x) > .7) node._onWall = n.x > 0 ? -1 : 1;
|
|
165
|
+
}
|
|
156
166
|
if (node._grounded) {
|
|
157
167
|
const footX = (t.x + corrected.x) * SCALE;
|
|
158
168
|
const footY = (t.y + corrected.y) * SCALE + charHalfHeight(node) - 2;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { m as diagnose } from "./loader-
|
|
2
|
+
import { m as diagnose } from "./loader-BwR0DxeM.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
|
-
import { F as PhysicsBody3D, I as RigidBody3D, N as Area3D, P as CharacterBody3D, R as Node3D, z as validateCollider3D } from "./gameplay-
|
|
4
|
+
import { F as PhysicsBody3D, I as RigidBody3D, N as Area3D, P as CharacterBody3D, R as Node3D, z as validateCollider3D } from "./gameplay-BxFtmfSe.js";
|
|
5
5
|
import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
|
|
6
|
-
import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets
|
|
6
|
+
import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-B6WiUsaO.js";
|
|
7
7
|
import { Euler, Matrix4, Quaternion, Vector3 } from "three";
|
|
8
8
|
//#region src/3d/physics/collider-lines.ts
|
|
9
9
|
/**
|
|
@@ -376,20 +376,53 @@ var Physics3D = class {
|
|
|
376
376
|
if (node.snapToGround && vy <= 0) this.kcc.enableSnapToGround(.1);
|
|
377
377
|
else this.kcc.disableSnapToGround();
|
|
378
378
|
this.kcc.setMaxSlopeClimbAngle(node.slopeLimitDeg * DEG);
|
|
379
|
+
let carryX = 0;
|
|
380
|
+
let carryY = 0;
|
|
381
|
+
let carryZ = 0;
|
|
382
|
+
if (e.ground && e.ground._physics === this && e.groundAt) {
|
|
383
|
+
const [gx, gy, gz] = worldPosition3D(e.ground);
|
|
384
|
+
carryX = gx - e.groundAt[0];
|
|
385
|
+
carryY = gy - e.groundAt[1];
|
|
386
|
+
carryZ = gz - e.groundAt[2];
|
|
387
|
+
} else e.ground = null;
|
|
379
388
|
const desired = {
|
|
380
|
-
x: (node.velocity[0] ?? 0) * this.lastDt,
|
|
381
|
-
y: vy * this.lastDt,
|
|
382
|
-
z: (node.velocity[2] ?? 0) * this.lastDt
|
|
389
|
+
x: (node.velocity[0] ?? 0) * this.lastDt + carryX,
|
|
390
|
+
y: vy * this.lastDt + carryY,
|
|
391
|
+
z: (node.velocity[2] ?? 0) * this.lastDt + carryZ
|
|
383
392
|
};
|
|
384
393
|
this.kcc.computeColliderMovement(e.collider, desired, this.R.QueryFilterFlags.EXCLUDE_SENSORS);
|
|
385
394
|
const c = this.kcc.computedMovement();
|
|
386
395
|
const t = e.body.translation();
|
|
396
|
+
const nx = t.x + c.x;
|
|
397
|
+
const ny = t.y + c.y;
|
|
398
|
+
const nz = t.z + c.z;
|
|
387
399
|
e.body.setNextKinematicTranslation({
|
|
388
|
-
x:
|
|
389
|
-
y:
|
|
390
|
-
z:
|
|
400
|
+
x: nx,
|
|
401
|
+
y: ny,
|
|
402
|
+
z: nz
|
|
391
403
|
});
|
|
392
404
|
node._grounded = this.kcc.computedGrounded();
|
|
405
|
+
if (node._grounded) {
|
|
406
|
+
const half = characterHalfHeight(node);
|
|
407
|
+
const hit = this.castRay([
|
|
408
|
+
nx,
|
|
409
|
+
ny - half + .05,
|
|
410
|
+
nz
|
|
411
|
+
], [
|
|
412
|
+
0,
|
|
413
|
+
-1,
|
|
414
|
+
0
|
|
415
|
+
], .4, node);
|
|
416
|
+
if (hit?.node && !(hit.node instanceof CharacterBody3D)) {
|
|
417
|
+
e.ground = hit.node;
|
|
418
|
+
const at = worldPosition3D(hit.node);
|
|
419
|
+
e.groundAt = [
|
|
420
|
+
at[0],
|
|
421
|
+
at[1],
|
|
422
|
+
at[2]
|
|
423
|
+
];
|
|
424
|
+
} else e.ground = null;
|
|
425
|
+
} else e.ground = null;
|
|
393
426
|
}
|
|
394
427
|
/** Rapier debug segments (meters). Null while debugDraw is off. */
|
|
395
428
|
debugLines() {
|
|
@@ -900,6 +933,19 @@ const posScratch = [
|
|
|
900
933
|
0
|
|
901
934
|
];
|
|
902
935
|
/** Writes into the shared scratch — consume before the next call. */
|
|
936
|
+
/**
|
|
937
|
+
* Half the character's own height, for placing a ground probe just inside its
|
|
938
|
+
* feet. Falls back to a metre — a probe an inch out of place misses a platform,
|
|
939
|
+
* and a body with no declared size is not a case worth guessing hard about.
|
|
940
|
+
*/
|
|
941
|
+
function characterHalfHeight(node) {
|
|
942
|
+
const collider = node.collider;
|
|
943
|
+
if (!collider) return 1;
|
|
944
|
+
if (collider.shape === "capsule" && typeof collider.height === "number") return collider.height / 2 + (collider.radius ?? 0);
|
|
945
|
+
if (collider.shape === "box" && Array.isArray(collider.size)) return (collider.size[1] ?? 2) / 2;
|
|
946
|
+
if (collider.shape === "sphere" && typeof collider.radius === "number") return collider.radius;
|
|
947
|
+
return 1;
|
|
948
|
+
}
|
|
903
949
|
function worldPosition3D(node) {
|
|
904
950
|
let x = 0;
|
|
905
951
|
let y = 0;
|
package/dist/react.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { N as Scene, n as BehaviorCtor, v as Engine } from "./behavior-CtPScDMo.js";
|
|
2
2
|
import { c as JsonValue } from "./schema-CcoWb32N.js";
|
|
3
3
|
import { CSSProperties, ReactNode } from "react";
|
|
4
4
|
|
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-QTfghzwM.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-CFNqoqOX.js").then((n) => n.n)).createGame2D(o)))(opts);
|
|
160
160
|
if (disposed) {
|
|
161
161
|
next.dispose();
|
|
162
162
|
return;
|