incanto 0.51.0 → 0.53.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 +86 -3
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +9 -3
- package/dist/3d.js +4 -4
- package/dist/{behavior-rZNfzVbH.d.ts → behavior-Do0Da56m.d.ts} +108 -0
- package/dist/{create-game-CkzKZ4v5.js → create-game-9D87XaiX.js} +112 -15
- package/dist/{create-game-BNaOC3Px.js → create-game-CDJ1lVqK.js} +21 -13
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +1 -1
- package/dist/{duplicate-EybyYeyL.js → duplicate-MNLMAcbz.js} +1 -1
- package/dist/editor.js +1931 -1579
- package/dist/{environment-presets-C08pOC6H.js → environment-presets-SkGanr2s.js} +3 -3
- package/dist/{gameplay-bStgtZBV.js → gameplay-CRYw_Q-T.js} +6 -4
- package/dist/gameplay.d.ts +1 -1
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +237 -5
- package/dist/index.js +9 -9
- package/dist/{loader-B2asghWa.js → loader-BTkHYrQn.js} +86 -50
- package/dist/{loader-Dkbn56KC.d.ts → loader-Cu_7kJDy.d.ts} +1 -1
- package/dist/{log-report-lxrQY9cH.js → log-report-CPFm4OXf.js} +0 -0
- package/dist/net.d.ts +15 -410
- package/dist/net.js +1 -822
- package/dist/{pathfinding-Bz34pvQD.d.ts → pathfinding-HNGFqGUZ.d.ts} +24 -1
- package/dist/{physics-2d-Ccq2L9R0.js → physics-2d-BhZZ-HAp.js} +2 -2
- package/dist/{physics-3d-B2c5KNYh.js → physics-3d-DmyO2oaN.js} +3 -3
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-CGq-Hee8.js → register-BTomIiYG.js} +305 -25
- package/dist/{register-B_BaaGx-.js → register-DROK2l7J.js} +3 -3
- package/dist/{registry-IyWCGe4q.js → registry-C7u42TID.js} +23 -1
- package/dist/{replay-DIP2_as4.d.ts → replay-9Fy6C10F.d.ts} +1 -1
- package/dist/{replay-BgKxGcXH.js → replay-DYNUL4BU.js} +195 -2
- package/dist/split-screen-CaF9hO7g.js +1267 -0
- package/dist/split-screen-DNmcX1Pz.d.ts +441 -0
- package/dist/{src-C3UwzYXl.js → src-C9xyZW7M.js} +1 -1
- package/dist/{teardown-BKTCzLek.js → teardown-Bw2aeyGI.js} +32 -2
- package/dist/{test-D2gRpk5V.js → test-CJRsciFk.js} +119 -22
- package/dist/test.d.ts +60 -5
- package/dist/test.js +3 -3
- package/dist/{touch-BoNg_MnF.js → touch-BnMyy9tr.js} +4 -4
- package/dist/vite.js +2 -2
- package/editor/assets/{agent8-DbX_msaO.js → agent8-PlFHzJsh.js} +1 -1
- package/editor/assets/{debug-C-kMxdl1.js → debug-CebV7CDW.js} +1 -1
- package/editor/assets/index-CdbsY31G.js +10958 -0
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +213 -0
- package/skills/incanto-assets.md +4 -1
- package/skills/incanto-audio.md +97 -10
- package/skills/incanto-building-2d-games.md +20 -3
- package/skills/incanto-editor.md +48 -11
- package/skills/incanto-gameplay-behaviors.md +14 -5
- package/skills/incanto-hud.md +7 -0
- package/skills/incanto-multiplayer.md +39 -3
- package/skills/incanto-node-reference.md +34 -0
- package/skills/incanto-physics-and-input.md +38 -0
- package/skills/incanto-verifying-your-game.md +75 -1
- package/skills/incanto-web-integration.md +1 -0
- package/templates/agent8-server.ts +79 -2
- package/templates-app/beacon-isle-3d/index.html +3 -3
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/index.html +3 -3
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/index.html +3 -3
- package/templates-app/village-quest-3d/package.json +1 -1
- package/dist/register-CLVhzWcI.js +0 -374
- package/editor/assets/index-CUc1U7wm.js +0 -10951
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { t as registerCoreNodes } from "./register-
|
|
1
|
+
import { t as registerCoreNodes } from "./register-BTomIiYG.js";
|
|
2
2
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
3
3
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
4
|
-
import { i as getNodeSchema, l as registerNode } from "./registry-
|
|
4
|
+
import { i as getNodeSchema, l as registerNode } from "./registry-C7u42TID.js";
|
|
5
5
|
import { t as createNoise2D } from "./noise-CGUMx44x.js";
|
|
6
6
|
import { i as ParticleSim, n as resolveFrames, o as PARTICLE_PRESET_NAMES, r as validateAnimationAliases, s as applyParticlePreset, t as resolveAnimation } from "./sprite-animation-D_p28jwU.js";
|
|
7
|
-
import { F as CharacterBody3D, I as PhysicsBody3D, L as RigidBody3D, N as WaterCutout3D, P as Area3D, R as StaticBody3D, U as colliderFootDrop, j as Water3D, z as Node3D } from "./gameplay-
|
|
7
|
+
import { F as CharacterBody3D, I as PhysicsBody3D, L as RigidBody3D, N as WaterCutout3D, P as Area3D, R as StaticBody3D, U as colliderFootDrop, j as Water3D, z as Node3D } from "./gameplay-CRYw_Q-T.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, ClampToEdgeWrapping, Color, ConeGeometry, CylinderGeometry, DataTexture, DirectionalLight, DoubleSide, DynamicDrawUsage, Euler, Group, IcosahedronGeometry, ImageBitmapLoader, InstancedBufferAttribute, InstancedMesh, LinearFilter, LinearMipmapLinearFilter, LoopOnce, LoopRepeat, Matrix4, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshPhysicalMaterial, MeshStandardMaterial, NearestFilter, NoBlending, NoColorSpace, NormalBlending, PerspectiveCamera, PlaneGeometry, PointLight, Points, PointsMaterial, Quaternion, QuaternionKeyframeTrack, RGBADepthPacking, RGBAFormat, RepeatWrapping, SRGBColorSpace, ShaderChunk, ShaderMaterial, SphereGeometry, Texture, TextureLoader, UniformsLib, UniformsUtils, Vector3, Vector4, VectorKeyframeTrack } from "three";
|
|
10
10
|
import { clone } from "three/addons/utils/SkeletonUtils.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { A as registerBehavior, T as Behavior,
|
|
1
|
+
import { A as registerBehavior, T as Behavior, b as effectiveOrder, f as Node, n as loadScene, p as SaveSlots } from "./loader-BTkHYrQn.js";
|
|
2
2
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
3
3
|
import { t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
4
|
-
import { t as duplicateNode } from "./duplicate-
|
|
4
|
+
import { t as duplicateNode } from "./duplicate-MNLMAcbz.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();
|
|
@@ -4374,7 +4374,8 @@ var Chase = class extends Behavior {
|
|
|
4374
4374
|
/** NodePath of the node to chase (resolved from THIS behavior's node). */
|
|
4375
4375
|
target: {
|
|
4376
4376
|
default: "",
|
|
4377
|
-
nodePath: true
|
|
4377
|
+
nodePath: true,
|
|
4378
|
+
required: true
|
|
4378
4379
|
},
|
|
4379
4380
|
/** Units per second toward the target. */
|
|
4380
4381
|
speed: { default: 60 },
|
|
@@ -4909,7 +4910,8 @@ var FollowCamera = class extends Behavior {
|
|
|
4909
4910
|
/** NodePath of the node to follow (relative to this node, or absolute). */
|
|
4910
4911
|
target: {
|
|
4911
4912
|
default: "",
|
|
4912
|
-
nodePath: true
|
|
4913
|
+
nodePath: true,
|
|
4914
|
+
required: true
|
|
4913
4915
|
},
|
|
4914
4916
|
/** Constant offset added to the target's position ([x,y] or [x,y,z]). */
|
|
4915
4917
|
offset: { default: [] },
|
package/dist/gameplay.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dt as Node, b as Engine, d as PropSchema, n as BehaviorCtor, t as Behavior } from "./behavior-
|
|
1
|
+
import { Dt as Node, b as Engine, d as PropSchema, n as BehaviorCtor, t as Behavior } from "./behavior-Do0Da56m.js";
|
|
2
2
|
import { c as JsonValue, s as JsonObject } from "./schema-CFeioQRE.js";
|
|
3
3
|
|
|
4
4
|
//#region src/gameplay/chase.d.ts
|
package/dist/gameplay.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as Chase, C as restartScene, D as DamageOnContact, E as phaseOf, O as Health, S as goToScene, T as DayNight, _ as Cooldown, a as Wander, b as Interactable, c as SavePoint, d as Patrol, f as PathFollow, g as CameraShake, h as Lifetime, i as WaveSpawner, k as Collector, l as Projectile, m as MoveTo, n as registerGameplayBehaviors, o as Spawner, p as Oscillate, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as Pickup, v as hitStop, w as FollowCamera, x as GameFlow, y as screenFlash } from "./gameplay-
|
|
1
|
+
import { A as Chase, C as restartScene, D as DamageOnContact, E as phaseOf, O as Health, S as goToScene, T as DayNight, _ as Cooldown, a as Wander, b as Interactable, c as SavePoint, d as Patrol, f as PathFollow, g as CameraShake, h as Lifetime, i as WaveSpawner, k as Collector, l as Projectile, m as MoveTo, n as registerGameplayBehaviors, o as Spawner, p as Oscillate, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as Pickup, v as hitStop, w as FollowCamera, x as GameFlow, y as screenFlash } from "./gameplay-CRYw_Q-T.js";
|
|
2
2
|
export { CameraShake, Chase, Collector, Cooldown, DamageOnContact, DayNight, FollowCamera, GAMEPLAY_BEHAVIORS, GameFlow, Health, Interactable, Lifetime, MoveTo, Oscillate, PathFollow, Patrol, Pickup, Projectile, SavePoint, ScoreKeeper, Spawner, Wander, WaveSpawner, ZombieAI, goToScene, hitStop, phaseOf, registerGameplayBehaviors, restartScene, screenFlash };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { $ as T_PREFIX, A as SettingsValues, At as LogEntry, B as captureBehaviors, C as EngineStats, Ct as MusicTrack, Dt as Node, E as DeviceHints, Et as BusName, F as BehaviorState, G as ORDER_GROUP_BASE, H as savesWithoutUid, I as RestoreReport, J as effectiveOrder, K as OrderGroup, L as SaveSlot, M as readDeviceHints, Mt as LogManager, N as suggestQuality, Nt as Signal, O as QualityTier, Ot as NodeLifecycle, P as Scene, Pt as SignalListener, Q as Localization, R as SaveSlots, S as Scheduler, St as MusicManager, T as RendererStats, Tt as AudioBuses, U as SaveStore, V as restoreBehaviors, W as createSaveStore, X as BASE_LOCALE, Y as resolveOrderGroups, Z as LocaleTables, _ as mergeStaticSignals, _t as SfxParams, a as clearBehaviors, at as isAudioContextAvailable, b as Engine, bt as synthSfx, c as registeredBehaviors, ct as Listener, d as PropSchema, dt as SpatialParams, et as suggestLocale, f as clearRegistry, ft as Vec3, g as getNodeType, gt as SFX_PRESET_NAMES, h as getNodeSignals, ht as SFX_PRESETS, i as behaviorSignals, it as SfxPlayOptions, j as qualityEnvironment, jt as LogLevel, k as Settings, kt as SceneTree, l as NodeCtor, lt as ROLLOFF_MODELS, m as getNodeSchema, mt as spatialPan, n as BehaviorCtor, nt as InputMap, o as getBehavior, ot as Voice, p as createNode, pt as spatialGain, q as OrderGroupTable, r as behaviorSchema, rt as SfxEngine, s as registerBehavior, st as VoicePreset, t as Behavior, tt as translationKey, u as PropDef, ut as RolloffModel, v as registerNode, vt as SfxWave, w as GameStats, wt as PlayMusicOptions, x as EngineOptions, xt as MusicBackend, y as registeredTypes, yt as SynthOptions, z as behaviorsWithoutSave } from "./behavior-
|
|
1
|
+
import { $ as T_PREFIX, A as SettingsValues, At as LogEntry, B as captureBehaviors, C as EngineStats, Ct as MusicTrack, Dt as Node, E as DeviceHints, Et as BusName, F as BehaviorState, G as ORDER_GROUP_BASE, H as savesWithoutUid, I as RestoreReport, J as effectiveOrder, K as OrderGroup, L as SaveSlot, M as readDeviceHints, Mt as LogManager, N as suggestQuality, Nt as Signal, O as QualityTier, Ot as NodeLifecycle, P as Scene, Pt as SignalListener, Q as Localization, R as SaveSlots, S as Scheduler, St as MusicManager, T as RendererStats, Tt as AudioBuses, U as SaveStore, V as restoreBehaviors, W as createSaveStore, X as BASE_LOCALE, Y as resolveOrderGroups, Z as LocaleTables, _ as mergeStaticSignals, _t as SfxParams, a as clearBehaviors, at as isAudioContextAvailable, b as Engine, bt as synthSfx, c as registeredBehaviors, ct as Listener, d as PropSchema, dt as SpatialParams, et as suggestLocale, f as clearRegistry, ft as Vec3, g as getNodeType, gt as SFX_PRESET_NAMES, h as getNodeSignals, ht as SFX_PRESETS, i as behaviorSignals, it as SfxPlayOptions, j as qualityEnvironment, jt as LogLevel, k as Settings, kt as SceneTree, l as NodeCtor, lt as ROLLOFF_MODELS, m as getNodeSchema, mt as spatialPan, n as BehaviorCtor, nt as InputMap, o as getBehavior, ot as Voice, p as createNode, pt as spatialGain, q as OrderGroupTable, r as behaviorSchema, rt as SfxEngine, s as registerBehavior, st as VoicePreset, t as Behavior, tt as translationKey, u as PropDef, ut as RolloffModel, v as registerNode, vt as SfxWave, w as GameStats, wt as PlayMusicOptions, x as EngineOptions, xt as MusicBackend, y as registeredTypes, yt as SynthOptions, z as behaviorsWithoutSave } from "./behavior-Do0Da56m.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-CFeioQRE.js";
|
|
3
|
-
import { n as loadScene, t as LoadSceneOptions } from "./loader-
|
|
3
|
+
import { n as loadScene, t as LoadSceneOptions } from "./loader-Cu_7kJDy.js";
|
|
4
4
|
import { i as resolveFrames, n as AnimationEntry, r as resolveAnimation, t as AnimationDef } from "./sprite-animation-CMr6f1K2.js";
|
|
5
5
|
import { n as ParticleSimConfig, r as ParticleView, t as ParticleSim } from "./particle-sim-BzJ1yxoE.js";
|
|
6
|
-
import { a as AudioElementLike, i as gridFromRows, n as PathGrid, o as AudioPlayer, r as findPath, t as FindPathOptions } from "./pathfinding-
|
|
7
|
-
import { a as startRecording, c as IncantoErrorDetails, i as replay, l as auditScene, n as ReplayEvent, o as IncantoError, r as ReplayJson, s as IncantoErrorCode, t as Recorder } from "./replay-
|
|
6
|
+
import { a as AudioElementLike, i as gridFromRows, n as PathGrid, o as AudioPlayer, r as findPath, t as FindPathOptions } from "./pathfinding-HNGFqGUZ.js";
|
|
7
|
+
import { a as startRecording, c as IncantoErrorDetails, i as replay, l as auditScene, n as ReplayEvent, o as IncantoError, r as ReplayJson, s as IncantoErrorCode, t as Recorder } from "./replay-9Fy6C10F.js";
|
|
8
8
|
|
|
9
9
|
//#region src/core/audio/crossfade.d.ts
|
|
10
10
|
/**
|
|
@@ -38,6 +38,7 @@ declare class WebAudioMusicBackend implements MusicBackend {
|
|
|
38
38
|
private ensure;
|
|
39
39
|
createTrack(src: string): MusicTrack;
|
|
40
40
|
unlock(): void;
|
|
41
|
+
dispose(): void;
|
|
41
42
|
}
|
|
42
43
|
//#endregion
|
|
43
44
|
//#region src/core/debug-draw.d.ts
|
|
@@ -189,6 +190,66 @@ type ParsedNodePath = {
|
|
|
189
190
|
};
|
|
190
191
|
declare function parseNodePath(path: string): ParsedNodePath;
|
|
191
192
|
//#endregion
|
|
193
|
+
//#region src/core/node-refs.d.ts
|
|
194
|
+
/** The scene-JSON shape this walks. */
|
|
195
|
+
interface RefNode {
|
|
196
|
+
name?: string;
|
|
197
|
+
type?: string;
|
|
198
|
+
props?: JsonObject;
|
|
199
|
+
script?: {
|
|
200
|
+
name?: string;
|
|
201
|
+
props?: JsonObject;
|
|
202
|
+
};
|
|
203
|
+
children?: RefNode[];
|
|
204
|
+
}
|
|
205
|
+
/** Why a written path leads nowhere. Structured so callers can localize it. */
|
|
206
|
+
type RefProblem = {
|
|
207
|
+
kind: "grammar";
|
|
208
|
+
message: string;
|
|
209
|
+
} | {
|
|
210
|
+
kind: "noMatch";
|
|
211
|
+
name: string;
|
|
212
|
+
} | {
|
|
213
|
+
kind: "ambiguous";
|
|
214
|
+
name: string;
|
|
215
|
+
count: number;
|
|
216
|
+
} | {
|
|
217
|
+
kind: "wrongRoot";
|
|
218
|
+
first: string;
|
|
219
|
+
root: string;
|
|
220
|
+
} | {
|
|
221
|
+
kind: "noChild";
|
|
222
|
+
parent: string;
|
|
223
|
+
segment: string;
|
|
224
|
+
} | {
|
|
225
|
+
kind: "aboveRoot";
|
|
226
|
+
};
|
|
227
|
+
type RefResult = {
|
|
228
|
+
ok: true;
|
|
229
|
+
path: number[];
|
|
230
|
+
} | {
|
|
231
|
+
ok: false;
|
|
232
|
+
problem: RefProblem;
|
|
233
|
+
};
|
|
234
|
+
/**
|
|
235
|
+
* Resolve `value` from the node at `owner`, the way the engine would.
|
|
236
|
+
*
|
|
237
|
+
* Note the asymmetry with connections, whose paths resolve from the SCENE ROOT:
|
|
238
|
+
* a prop's path resolves from the node holding it, which is why `'../Skin'` is
|
|
239
|
+
* the documented default of `CharacterController3D.skinPath` and would mean
|
|
240
|
+
* nothing in a connection.
|
|
241
|
+
*/
|
|
242
|
+
declare function resolveRefInJson(root: RefNode | undefined, owner: readonly number[], value: string): RefResult;
|
|
243
|
+
/** The problem in English, for `incanto-check` and as the editor's base text. */
|
|
244
|
+
declare function describeRefProblem(problem: RefProblem, value: string): string;
|
|
245
|
+
/**
|
|
246
|
+
* Scene lints for node-path props that point at nothing.
|
|
247
|
+
*
|
|
248
|
+
* An EMPTY value is not reported: `''` is the default of most of these props and
|
|
249
|
+
* means "not set", which is a choice rather than a typo.
|
|
250
|
+
*/
|
|
251
|
+
declare function nodeRefWarnings(scene: JsonObject): string[];
|
|
252
|
+
//#endregion
|
|
192
253
|
//#region src/core/nodes/hud.d.ts
|
|
193
254
|
/**
|
|
194
255
|
* DOM-backed HUD widgets — the layer 18 of 22 example games hand-rolled.
|
|
@@ -637,6 +698,177 @@ declare class UiSelect extends HudWidgetBase {
|
|
|
637
698
|
private fillOptions;
|
|
638
699
|
protected override _sync(): void;
|
|
639
700
|
}
|
|
701
|
+
/**
|
|
702
|
+
* The language picker, done — because every game needs the same one.
|
|
703
|
+
*
|
|
704
|
+
* A plain `UiSelect` bound to the locale would take a behavior, a signal
|
|
705
|
+
* connection, and the knowledge that `Settings` persists it: three things an
|
|
706
|
+
* agent has to get right to ship a feature the engine already has. This is one
|
|
707
|
+
* node.
|
|
708
|
+
*
|
|
709
|
+
* ```json
|
|
710
|
+
* { "name": "Language", "type": "UiLanguageSelect",
|
|
711
|
+
* "props": { "label": "@t:settings.language" } }
|
|
712
|
+
* ```
|
|
713
|
+
*
|
|
714
|
+
* Options are the locales the SCENE declares, so a game shipping only English
|
|
715
|
+
* shows only English and the widget quietly costs nothing. Each is labeled with
|
|
716
|
+
* its own endonym, because a player who cannot read the language currently on
|
|
717
|
+
* screen still has to be able to find theirs.
|
|
718
|
+
*/
|
|
719
|
+
declare class UiLanguageSelect extends UiSelect {
|
|
720
|
+
static override readonly typeName: string;
|
|
721
|
+
static override readonly props: PropSchema;
|
|
722
|
+
override label: string;
|
|
723
|
+
/** Last locale we PUSHED into `value`, to tell an engine change from a player one. */
|
|
724
|
+
private lastLocale;
|
|
725
|
+
protected override _sync(): void;
|
|
726
|
+
protected override _optionLabel(value: string): string;
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* A select bound to one persisted setting — the shape all three graphics
|
|
730
|
+
* controls share.
|
|
731
|
+
*
|
|
732
|
+
* The engine owns quality tiers, the frame cap and the resolution scale, and
|
|
733
|
+
* every one of them was reachable only from TypeScript. A vibe-coded game whose
|
|
734
|
+
* whole world is JSON could not put a graphics menu on screen without a
|
|
735
|
+
* behavior, a signal connection, and the knowledge that `Settings` persists —
|
|
736
|
+
* which is how "supports low-end devices" quietly becomes "does not".
|
|
737
|
+
*
|
|
738
|
+
* Subclasses say which setting, what the options are, and what they read as.
|
|
739
|
+
*/
|
|
740
|
+
declare abstract class UiSettingSelect extends UiSelect {
|
|
741
|
+
/** Last value we PUSHED into the select, to tell an engine change from a player one. */
|
|
742
|
+
private lastPushed;
|
|
743
|
+
/** The settings key this control owns. */
|
|
744
|
+
protected abstract _key(): string;
|
|
745
|
+
/** The stored value, as the string the select carries. */
|
|
746
|
+
protected abstract _read(engine: NonNullable<ReturnType<UiSettingSelect["_engine"]>>): string;
|
|
747
|
+
/** Apply a player's pick. */
|
|
748
|
+
protected abstract _write(engine: NonNullable<ReturnType<UiSettingSelect["_engine"]>>, value: string): void;
|
|
749
|
+
protected _engine(): Engine | null;
|
|
750
|
+
/**
|
|
751
|
+
* The translated option label, or the English one.
|
|
752
|
+
*
|
|
753
|
+
* `locale.t` returns the KEY when nothing declares it, and a menu reading
|
|
754
|
+
* `settings.quality.high` is worse than one reading `High`. English is the
|
|
755
|
+
* base language and the fallback, always.
|
|
756
|
+
*/
|
|
757
|
+
protected _tOr(key: string, fallback: string): string;
|
|
758
|
+
protected override _sync(): void;
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* The graphics quality picker.
|
|
762
|
+
*
|
|
763
|
+
* ```json
|
|
764
|
+
* { "name": "Quality", "type": "UiQualitySelect" }
|
|
765
|
+
* ```
|
|
766
|
+
*
|
|
767
|
+
* Writes through `chooseQuality`, NOT `set('quality')`: a tier a person picked
|
|
768
|
+
* has to survive the next launch's device detection, and the two are
|
|
769
|
+
* indistinguishable afterwards unless the choice is recorded as one.
|
|
770
|
+
*
|
|
771
|
+
* Shadows, bloom, post and clouds follow immediately. Antialiasing follows on
|
|
772
|
+
* the next launch — it is a WebGL context attribute and cannot change while a
|
|
773
|
+
* context exists.
|
|
774
|
+
*/
|
|
775
|
+
declare class UiQualitySelect extends UiSettingSelect {
|
|
776
|
+
static override readonly typeName: string;
|
|
777
|
+
static override readonly props: PropSchema;
|
|
778
|
+
override label: string;
|
|
779
|
+
override options: string;
|
|
780
|
+
protected override _key(): string;
|
|
781
|
+
protected override _read(engine: Engine): string;
|
|
782
|
+
protected override _write(engine: Engine, value: string): void;
|
|
783
|
+
protected override _optionLabel(value: string): string;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* The frame-rate cap: fewer frames, a cooler phone, a longer battery.
|
|
787
|
+
*
|
|
788
|
+
* ```json
|
|
789
|
+
* { "name": "FrameCap", "type": "UiFrameCapSelect" }
|
|
790
|
+
* ```
|
|
791
|
+
*
|
|
792
|
+
* `0` is uncapped and is the default — a cap nobody asked for is a downgrade.
|
|
793
|
+
* The cap gates the whole frame, so it saves the CPU as well as the GPU.
|
|
794
|
+
*/
|
|
795
|
+
declare class UiFrameCapSelect extends UiSettingSelect {
|
|
796
|
+
static override readonly typeName: string;
|
|
797
|
+
static override readonly props: PropSchema;
|
|
798
|
+
override label: string;
|
|
799
|
+
override options: string;
|
|
800
|
+
protected override _key(): string;
|
|
801
|
+
protected override _read(engine: Engine): string;
|
|
802
|
+
protected override _write(engine: Engine, value: string): void;
|
|
803
|
+
protected override _optionLabel(value: string): string;
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* The resolution scale — the cheapest frames on a weak GPU.
|
|
807
|
+
*
|
|
808
|
+
* ```json
|
|
809
|
+
* { "name": "Resolution", "type": "UiRenderScaleSelect" }
|
|
810
|
+
* ```
|
|
811
|
+
*
|
|
812
|
+
* At 75% the fragment shaders run over 56% of the pixels for a slightly softer
|
|
813
|
+
* image and nothing else, where dropping a quality tier costs the shadows
|
|
814
|
+
* outright. Reads as a percentage, because `0.75` means nothing to a player.
|
|
815
|
+
*/
|
|
816
|
+
declare class UiRenderScaleSelect extends UiSettingSelect {
|
|
817
|
+
static override readonly typeName: string;
|
|
818
|
+
static override readonly props: PropSchema;
|
|
819
|
+
override label: string;
|
|
820
|
+
override options: string;
|
|
821
|
+
protected override _key(): string;
|
|
822
|
+
protected override _read(engine: Engine): string;
|
|
823
|
+
protected override _write(engine: Engine, value: string): void;
|
|
824
|
+
protected override _optionLabel(value: string): string;
|
|
825
|
+
}
|
|
826
|
+
/** The three buses a player is ever offered a slider for. */
|
|
827
|
+
declare const VOLUME_BUSES: readonly ["master", "sfx", "music"];
|
|
828
|
+
type VolumeBus = (typeof VOLUME_BUSES)[number];
|
|
829
|
+
/**
|
|
830
|
+
* The volume slider — the settings row every game has.
|
|
831
|
+
*
|
|
832
|
+
* ```json
|
|
833
|
+
* { "name": "Music", "type": "UiVolumeSlider", "props": { "bus": "music" } }
|
|
834
|
+
* ```
|
|
835
|
+
*
|
|
836
|
+
* The graphics controls above became nodes because a game whose whole world is
|
|
837
|
+
* JSON could not put a menu on screen without a behavior, a signal connection
|
|
838
|
+
* and the knowledge that `Settings` persists. All of that was just as true of
|
|
839
|
+
* volume, which is the control a player looks for FIRST and the only one some
|
|
840
|
+
* games need at all — so an audio menu meant hand-rolled DOM, and hand-rolled
|
|
841
|
+
* DOM is out of scene JSON, out of the editor, and out of every headless check.
|
|
842
|
+
*
|
|
843
|
+
* It writes the bus; the bus persists itself (`bindAudio`, which
|
|
844
|
+
* `createGame2D/3D` wire), so there is nothing to save.
|
|
845
|
+
*/
|
|
846
|
+
declare class UiVolumeSlider extends UiSlider {
|
|
847
|
+
static override readonly typeName: string;
|
|
848
|
+
static override readonly props: PropSchema;
|
|
849
|
+
bus: VolumeBus;
|
|
850
|
+
/** Last value we PUSHED in, to tell an engine-side change from a player drag. */
|
|
851
|
+
private lastPushed;
|
|
852
|
+
protected override _build(): HTMLElement;
|
|
853
|
+
protected override _sync(): void;
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* The mute switch.
|
|
857
|
+
*
|
|
858
|
+
* ```json
|
|
859
|
+
* { "name": "Mute", "type": "UiMuteToggle" }
|
|
860
|
+
* ```
|
|
861
|
+
*
|
|
862
|
+
* Checked means silent. Like the slider it writes `engine.audio`, which
|
|
863
|
+
* persists itself.
|
|
864
|
+
*/
|
|
865
|
+
declare class UiMuteToggle extends UiToggle {
|
|
866
|
+
static override readonly typeName: string;
|
|
867
|
+
static override readonly props: PropSchema;
|
|
868
|
+
private lastPushed;
|
|
869
|
+
protected override _build(): HTMLElement;
|
|
870
|
+
protected override _sync(): void;
|
|
871
|
+
}
|
|
640
872
|
//#endregion
|
|
641
873
|
//#region src/core/noise.d.ts
|
|
642
874
|
/**
|
|
@@ -857,4 +1089,4 @@ declare function computeViewport(canvasW: number, canvasH: number, viewport: {
|
|
|
857
1089
|
/** Engine version. Kept in sync with package.json by the release pipeline. */
|
|
858
1090
|
declare const VERSION: string;
|
|
859
1091
|
//#endregion
|
|
860
|
-
export { type AnimationDef, type AnimationEntry, type AssetFailure, AudioBuses, type AudioElementLike, AudioPlayer, BASE_LOCALE, Behavior, type BehaviorCtor, type BehaviorState, type BusName, CONST_REF_KEY, type ComputedViewport, type ConnectionJson, type CrossfadeGains, type DebugLineSource, type DeviceHints, type DriveScript, type DriveStep, Engine, type EngineOptions, type EngineStats, type FindPathOptions, type GameStats, type GroupedLog, type HudAnchor, HudLayer, IncantoError, type IncantoErrorCode, type IncantoErrorDetails, InputMap, type JsonKind, type JsonObject, type JsonValue, type Listener, type LiveInput, type LiveReport, type LoadSceneOptions, type LocaleTables, Localization, type LogEntry, type LogLevel, LogManager, type MusicBackend, MusicManager, type MusicTrack, Node, type NodeCtor, type NodeJson, type NodeLifecycle, ORDER_GROUP_BASE, type OrderGroup, type OrderGroupTable, 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, type RestoreReport, Rng, type RolloffModel, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, type SaveSlot, SaveSlots, 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, T_PREFIX, 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, behaviorSchema, behaviorSignals, behaviorsWithoutSave, captureBehaviors, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, logReport, logText, mergeStaticSignals, newUid, parseDrive, parseNodePath, preloadUrls, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveAnimation, resolveConstants, resolveFrames, resolveOrderGroups, resolveRendering, resolveViewport, restoreBehaviors, savesWithoutUid, serializeNode, spatialGain, spatialPan, startRecording, suggestLocale, suggestQuality, synthSfx, translationKey };
|
|
1092
|
+
export { type AnimationDef, type AnimationEntry, type AssetFailure, AudioBuses, type AudioElementLike, AudioPlayer, BASE_LOCALE, Behavior, type BehaviorCtor, type BehaviorState, type BusName, CONST_REF_KEY, type ComputedViewport, type ConnectionJson, type CrossfadeGains, type DebugLineSource, type DeviceHints, type DriveScript, type DriveStep, Engine, type EngineOptions, type EngineStats, type FindPathOptions, type GameStats, type GroupedLog, type HudAnchor, HudLayer, IncantoError, type IncantoErrorCode, type IncantoErrorDetails, InputMap, type JsonKind, type JsonObject, type JsonValue, type Listener, type LiveInput, type LiveReport, type LoadSceneOptions, type LocaleTables, Localization, type LogEntry, type LogLevel, LogManager, type MusicBackend, MusicManager, type MusicTrack, Node, type NodeCtor, type NodeJson, type NodeLifecycle, ORDER_GROUP_BASE, type OrderGroup, type OrderGroupTable, 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 RefNode, type RefProblem, type RefResult, type RendererStats, type ReplayEvent, type ReplayJson, type ResolvedRendering, type ResolvedViewport, type RestoreReport, Rng, type RolloffModel, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, type SaveSlot, SaveSlots, 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, T_PREFIX, Timer, TouchControls, type TouchControlsOptions, UiBanner, UiBar, UiButton, UiDialogue, UiFrameCapSelect, UiImage, UiLanguageSelect, UiMuteToggle, UiPanel, UiQualitySelect, UiRenderScaleSelect, UiSelect, UiSlider, UiText, UiToggle, UiVolumeSlider, VERSION, type Vec3, type ViewportFit, type Voice, type VoicePreset, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, behaviorSchema, behaviorSignals, behaviorsWithoutSave, captureBehaviors, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, describeRefProblem, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, logReport, logText, mergeStaticSignals, newUid, nodeRefWarnings, parseDrive, parseNodePath, preloadUrls, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveAnimation, resolveConstants, resolveFrames, resolveOrderGroups, resolveRefInJson, resolveRendering, resolveViewport, restoreBehaviors, savesWithoutUid, serializeNode, spatialGain, spatialPan, startRecording, suggestLocale, suggestQuality, synthSfx, translationKey };
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { A as registerBehavior,
|
|
2
|
-
import { A as
|
|
1
|
+
import { A as registerBehavior, D as behaviorSignals, E as behaviorSchema, M as Signal, O as clearBehaviors, S as InputMap, T as Behavior, _ as savesWithoutUid, a as SCENE_FORMAT, b as effectiveOrder, c as SceneTree, d as resolveConstants, f as Node, g as restoreBehaviors, h as captureBehaviors, i as serializeNode, j as registeredBehaviors, k as getBehavior, l as CONST_REF_KEY, m as behaviorsWithoutSave, n as loadScene, o as computeViewport, p as SaveSlots, r as Scene, s as resolveViewport, u as isConstRef, v as createSaveStore, w as parseNodePath, x as resolveOrderGroups, y as ORDER_GROUP_BASE } from "./loader-BTkHYrQn.js";
|
|
2
|
+
import { A as Localization, B as SFX_PRESET_NAMES, D as suggestQuality, E as readDeviceHints, F as isAudioContextAvailable, G as fadeGain, H as MusicManager, I as ROLLOFF_MODELS, K as AudioBuses, L as spatialGain, M as suggestLocale, N as translationKey, O as LogManager, P as SfxEngine, R as spatialPan, S as Settings, U as WebAudioMusicBackend, V as synthSfx, W as crossfadeGains, _ as UiBanner, a as UiMuteToggle, b as AudioPlayer, c as UiRenderScaleSelect, d as UiToggle, f as UiVolumeSlider, g as HudLayer, h as UiDialogue, i as UiLanguageSelect, j as T_PREFIX, k as BASE_LOCALE, l as UiSelect, m as UiButton, n as UiFrameCapSelect, o as UiPanel, p as Timer, r as UiImage, s as UiQualitySelect, t as registerCoreNodes, u as UiSlider, v as UiBar, w as qualityEnvironment, x as Engine, y as UiText, z as SFX_PRESETS } from "./register-BTomIiYG.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
5
|
-
import { n as startRecording, r as auditScene, t as replay } from "./replay-BgKxGcXH.js";
|
|
6
5
|
import { n as jsonEquals, r as jsonKind, t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
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-
|
|
8
|
-
import { n as
|
|
6
|
+
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-C7u42TID.js";
|
|
7
|
+
import { a as nodeRefWarnings, i as describeRefProblem, n as startRecording, o as resolveRefInJson, r as auditScene, t as replay } from "./replay-DYNUL4BU.js";
|
|
8
|
+
import { n as logText, r as parseDrive, t as logReport } from "./log-report-CPFm4OXf.js";
|
|
9
9
|
import { t as createNoise2D } from "./noise-CGUMx44x.js";
|
|
10
10
|
import { a as PARTICLE_PRESETS, i as ParticleSim, n as resolveFrames, o as PARTICLE_PRESET_NAMES, s as applyParticlePreset, t as resolveAnimation } from "./sprite-animation-D_p28jwU.js";
|
|
11
|
-
import { a as findPath, i as preloadUrls, n as newUid, o as gridFromRows, r as assetUrls, t as VERSION } from "./src-
|
|
12
|
-
import { i as resolveRendering, n as attachTouchControls, r as joystickVector, t as TouchControls } from "./touch-
|
|
13
|
-
import { t as duplicateNode } from "./duplicate-
|
|
14
|
-
export { AudioBuses, AudioPlayer, BASE_LOCALE, Behavior, CONST_REF_KEY, Engine, HudLayer, IncantoError, InputMap, Localization, LogManager, MusicManager, Node, ORDER_GROUP_BASE, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, ParticleSim, ROLLOFF_MODELS, Rng, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, SaveSlots, Scene, SceneTree, Settings, SfxEngine, Signal, T_PREFIX, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiImage, UiPanel, UiSelect, UiSlider, UiText, UiToggle, VERSION, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, behaviorSchema, behaviorSignals, behaviorsWithoutSave, captureBehaviors, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, logReport, logText, mergeStaticSignals, newUid, parseDrive, parseNodePath, preloadUrls, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveAnimation, resolveConstants, resolveFrames, resolveOrderGroups, resolveRendering, resolveViewport, restoreBehaviors, savesWithoutUid, serializeNode, spatialGain, spatialPan, startRecording, suggestLocale, suggestQuality, synthSfx, translationKey };
|
|
11
|
+
import { a as findPath, i as preloadUrls, n as newUid, o as gridFromRows, r as assetUrls, t as VERSION } from "./src-C9xyZW7M.js";
|
|
12
|
+
import { i as resolveRendering, n as attachTouchControls, r as joystickVector, t as TouchControls } from "./touch-BnMyy9tr.js";
|
|
13
|
+
import { t as duplicateNode } from "./duplicate-MNLMAcbz.js";
|
|
14
|
+
export { AudioBuses, AudioPlayer, BASE_LOCALE, Behavior, CONST_REF_KEY, Engine, HudLayer, IncantoError, InputMap, Localization, LogManager, MusicManager, Node, ORDER_GROUP_BASE, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, ParticleSim, ROLLOFF_MODELS, Rng, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, SaveSlots, Scene, SceneTree, Settings, SfxEngine, Signal, T_PREFIX, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiFrameCapSelect, UiImage, UiLanguageSelect, UiMuteToggle, UiPanel, UiQualitySelect, UiRenderScaleSelect, UiSelect, UiSlider, UiText, UiToggle, UiVolumeSlider, VERSION, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, behaviorSchema, behaviorSignals, behaviorsWithoutSave, captureBehaviors, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, describeRefProblem, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, logReport, logText, mergeStaticSignals, newUid, nodeRefWarnings, parseDrive, parseNodePath, preloadUrls, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveAnimation, resolveConstants, resolveFrames, resolveOrderGroups, resolveRefInJson, resolveRendering, resolveViewport, restoreBehaviors, savesWithoutUid, serializeNode, spatialGain, spatialPan, startRecording, suggestLocale, suggestQuality, synthSfx, translationKey };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
2
2
|
import { n as jsonEquals, t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
3
|
-
import { c as mergeStaticSignals, i as getNodeSchema, r as createNode, s as mergeStaticProps, t as applySchemaProps } from "./registry-
|
|
3
|
+
import { c as mergeStaticSignals, i as getNodeSchema, r as createNode, s as mergeStaticProps, t as applySchemaProps } from "./registry-C7u42TID.js";
|
|
4
4
|
//#region src/core/signal.ts
|
|
5
5
|
var Signal = class {
|
|
6
6
|
connections = [];
|
|
@@ -135,6 +135,36 @@ function createBehavior(name, props) {
|
|
|
135
135
|
return behavior;
|
|
136
136
|
}
|
|
137
137
|
//#endregion
|
|
138
|
+
//#region src/core/node-path.ts
|
|
139
|
+
function parseNodePath(path) {
|
|
140
|
+
if (path === "") throw new IncantoError("BAD_NODE_PATH", "Node path must not be empty.");
|
|
141
|
+
if (path.startsWith("%")) {
|
|
142
|
+
const name = path.slice(1);
|
|
143
|
+
if (name === "" || name.includes("/") || name.includes("%")) throw new IncantoError("BAD_NODE_PATH", `Invalid unique-name path '${path}'. Expected '%NodeName'.`);
|
|
144
|
+
return {
|
|
145
|
+
kind: "unique",
|
|
146
|
+
name
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (path === ".") return {
|
|
150
|
+
kind: "relative",
|
|
151
|
+
segments: []
|
|
152
|
+
};
|
|
153
|
+
const absolute = path.startsWith("/");
|
|
154
|
+
const body = absolute ? path.slice(1) : path;
|
|
155
|
+
if (body === "" || body.split("/").some((s) => s === "")) throw new IncantoError("BAD_NODE_PATH", `Invalid node path '${path}'. Segments must be non-empty (no leading/trailing/double '/').`);
|
|
156
|
+
const segments = body.split("/");
|
|
157
|
+
for (const seg of segments) {
|
|
158
|
+
if (seg.includes("%")) throw new IncantoError("BAD_NODE_PATH", `Invalid node path '${path}'. '%' is only allowed as a whole-path prefix ('%Name').`);
|
|
159
|
+
if (seg === ".") throw new IncantoError("BAD_NODE_PATH", `Invalid node path '${path}'. '.' is only valid as the whole path — drop the './' prefix.`);
|
|
160
|
+
}
|
|
161
|
+
if (absolute && segments.includes("..")) throw new IncantoError("BAD_NODE_PATH", `Invalid node path '${path}'. Absolute paths must not contain '..'.`);
|
|
162
|
+
return {
|
|
163
|
+
kind: absolute ? "absolute" : "relative",
|
|
164
|
+
segments
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
//#endregion
|
|
138
168
|
//#region src/core/diagnostics.ts
|
|
139
169
|
function diagnose(engine, level, ...parts) {
|
|
140
170
|
engine?.log[level](...parts);
|
|
@@ -191,12 +221,9 @@ var InputMap = class {
|
|
|
191
221
|
};
|
|
192
222
|
return;
|
|
193
223
|
}
|
|
194
|
-
const el = target;
|
|
195
|
-
const scaleX = typeof el.width === "number" && el.width > 0 ? el.width / rect.width : 1;
|
|
196
|
-
const scaleY = typeof el.height === "number" && el.height > 0 ? el.height / rect.height : 1;
|
|
197
224
|
this.pointerPos = {
|
|
198
|
-
x:
|
|
199
|
-
y:
|
|
225
|
+
x: clientX - rect.left,
|
|
226
|
+
y: clientY - rect.top
|
|
200
227
|
};
|
|
201
228
|
}
|
|
202
229
|
pointerPos = null;
|
|
@@ -388,36 +415,69 @@ var InputMap = class {
|
|
|
388
415
|
};
|
|
389
416
|
return disconnect;
|
|
390
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* Pointer input from a mouse, a FINGER or a pen — one code path.
|
|
420
|
+
*
|
|
421
|
+
* This used to bind `mousedown`/`mousemove`/`mouseup`, which on a phone only
|
|
422
|
+
* arrive as COMPATIBILITY events: delayed until the browser has decided the
|
|
423
|
+
* touch is not a scroll, never fired for drags or multi-touch, and suppressed
|
|
424
|
+
* outright once the surface claims its gestures with `touch-action: none`.
|
|
425
|
+
* So every genre the comment below lists — match-3, tower defense, card,
|
|
426
|
+
* point-and-click, RTS — was mouse-only on the device most of them are played
|
|
427
|
+
* on. Pointer events cover all three input kinds and fire immediately.
|
|
428
|
+
*
|
|
429
|
+
* Only the PRIMARY pointer drives it: a second finger (the one on the virtual
|
|
430
|
+
* stick) must not also swing the camera.
|
|
431
|
+
*/
|
|
391
432
|
attachPointer(target, opts) {
|
|
392
433
|
let buttonsHeld = 0;
|
|
434
|
+
/** The pointer that pressed on THIS target; others are somebody else's. */
|
|
435
|
+
let activeId = null;
|
|
393
436
|
const onDown = (e) => {
|
|
437
|
+
if (!e.isPrimary) return;
|
|
438
|
+
activeId = e.pointerId;
|
|
394
439
|
buttonsHeld++;
|
|
395
440
|
this.setPointerPosition(e.clientX, e.clientY, target);
|
|
396
441
|
this.handleMouseButton(e.button, true);
|
|
397
442
|
if (opts?.lockOnClick && document.pointerLockElement !== target) target.requestPointerLock?.();
|
|
398
443
|
};
|
|
399
444
|
const onUp = (e) => {
|
|
445
|
+
if (activeId !== null && e.pointerId !== activeId) return;
|
|
446
|
+
activeId = null;
|
|
400
447
|
buttonsHeld = Math.max(0, buttonsHeld - 1);
|
|
401
448
|
this.handleMouseButton(e.button, false);
|
|
402
449
|
};
|
|
403
450
|
const onMove = (e) => {
|
|
451
|
+
if (activeId !== null && e.pointerId !== activeId) return;
|
|
404
452
|
this.setPointerPosition(e.clientX, e.clientY, target);
|
|
405
|
-
if (document.pointerLockElement === target || buttonsHeld > 0)
|
|
453
|
+
if (document.pointerLockElement === target || buttonsHeld > 0) {
|
|
454
|
+
const dx = e.movementX || this.pointerDelta().x;
|
|
455
|
+
const dy = e.movementY || this.pointerDelta().y;
|
|
456
|
+
this.handlePointerMove(dx, dy);
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
const onCancel = (e) => {
|
|
460
|
+
if (activeId !== null && e.pointerId !== activeId) return;
|
|
461
|
+
activeId = null;
|
|
462
|
+
buttonsHeld = 0;
|
|
463
|
+
this.handleMouseButton(0, false);
|
|
406
464
|
};
|
|
407
465
|
const onWheel = (e) => {
|
|
408
466
|
e.preventDefault();
|
|
409
467
|
this.handleWheel(e.deltaY);
|
|
410
468
|
};
|
|
411
469
|
const onContext = (e) => e.preventDefault();
|
|
412
|
-
target.addEventListener("
|
|
413
|
-
window.addEventListener("
|
|
414
|
-
window.addEventListener("
|
|
470
|
+
target.addEventListener("pointerdown", onDown);
|
|
471
|
+
window.addEventListener("pointerup", onUp);
|
|
472
|
+
window.addEventListener("pointermove", onMove);
|
|
473
|
+
window.addEventListener("pointercancel", onCancel);
|
|
415
474
|
target.addEventListener("wheel", onWheel, { passive: false });
|
|
416
475
|
target.addEventListener("contextmenu", onContext);
|
|
417
476
|
const detach = () => {
|
|
418
|
-
target.removeEventListener("
|
|
419
|
-
window.removeEventListener("
|
|
420
|
-
window.removeEventListener("
|
|
477
|
+
target.removeEventListener("pointerdown", onDown);
|
|
478
|
+
window.removeEventListener("pointerup", onUp);
|
|
479
|
+
window.removeEventListener("pointermove", onMove);
|
|
480
|
+
window.removeEventListener("pointercancel", onCancel);
|
|
421
481
|
target.removeEventListener("wheel", onWheel);
|
|
422
482
|
target.removeEventListener("contextmenu", onContext);
|
|
423
483
|
};
|
|
@@ -574,6 +634,12 @@ var InputMap = class {
|
|
|
574
634
|
* never looked at `input` at all. A typo there ("keys": "KeyW" instead of
|
|
575
635
|
* ["KeyW"]) passed the check and threw in the browser at boot.
|
|
576
636
|
*/
|
|
637
|
+
const DIRECTIONS = [
|
|
638
|
+
"up",
|
|
639
|
+
"down",
|
|
640
|
+
"left",
|
|
641
|
+
"right"
|
|
642
|
+
];
|
|
577
643
|
function parseInputDecls(decls) {
|
|
578
644
|
const out = /* @__PURE__ */ new Map();
|
|
579
645
|
for (const [name, raw] of Object.entries(decls)) {
|
|
@@ -589,12 +655,12 @@ function parseInputDecls(decls) {
|
|
|
589
655
|
});
|
|
590
656
|
} else if (decl.type === "vector2") {
|
|
591
657
|
const dirs = decl.keys;
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
"
|
|
596
|
-
"right"
|
|
597
|
-
|
|
658
|
+
const missing = DIRECTIONS.filter((dir) => !Array.isArray(dirs?.[dir]));
|
|
659
|
+
if (missing.length > 0) {
|
|
660
|
+
const atTopLevel = DIRECTIONS.filter((dir) => Array.isArray(decl[dir]));
|
|
661
|
+
const where = atTopLevel.length > 0 ? ` — ${atTopLevel.join(", ")} ${atTopLevel.length === 1 ? "is" : "are"} at the top level, not under "keys"` : "";
|
|
662
|
+
throw new IncantoError("BAD_FORMAT", `Input action '${name}': a vector2 needs ${missing.join(", ")} as arrays of KeyboardEvent.code strings under "keys"${where}. Like this: { "type": "vector2", "keys": { "up": ["KeyW"], "down": ["KeyS"], "left": ["KeyA"], "right": ["KeyD"] } }`);
|
|
663
|
+
}
|
|
598
664
|
if (decl.touch !== void 0 && decl.touch !== "joystick") throw new IncantoError("BAD_FORMAT", `Input action '${name}': vector2 "touch" must be 'joystick', got ${JSON.stringify(decl.touch)}.`);
|
|
599
665
|
const d = dirs;
|
|
600
666
|
out.set(name, {
|
|
@@ -979,36 +1045,6 @@ function savesWithoutUid(root) {
|
|
|
979
1045
|
return out;
|
|
980
1046
|
}
|
|
981
1047
|
//#endregion
|
|
982
|
-
//#region src/core/node-path.ts
|
|
983
|
-
function parseNodePath(path) {
|
|
984
|
-
if (path === "") throw new IncantoError("BAD_NODE_PATH", "Node path must not be empty.");
|
|
985
|
-
if (path.startsWith("%")) {
|
|
986
|
-
const name = path.slice(1);
|
|
987
|
-
if (name === "" || name.includes("/") || name.includes("%")) throw new IncantoError("BAD_NODE_PATH", `Invalid unique-name path '${path}'. Expected '%NodeName'.`);
|
|
988
|
-
return {
|
|
989
|
-
kind: "unique",
|
|
990
|
-
name
|
|
991
|
-
};
|
|
992
|
-
}
|
|
993
|
-
if (path === ".") return {
|
|
994
|
-
kind: "relative",
|
|
995
|
-
segments: []
|
|
996
|
-
};
|
|
997
|
-
const absolute = path.startsWith("/");
|
|
998
|
-
const body = absolute ? path.slice(1) : path;
|
|
999
|
-
if (body === "" || body.split("/").some((s) => s === "")) throw new IncantoError("BAD_NODE_PATH", `Invalid node path '${path}'. Segments must be non-empty (no leading/trailing/double '/').`);
|
|
1000
|
-
const segments = body.split("/");
|
|
1001
|
-
for (const seg of segments) {
|
|
1002
|
-
if (seg.includes("%")) throw new IncantoError("BAD_NODE_PATH", `Invalid node path '${path}'. '%' is only allowed as a whole-path prefix ('%Name').`);
|
|
1003
|
-
if (seg === ".") throw new IncantoError("BAD_NODE_PATH", `Invalid node path '${path}'. '.' is only valid as the whole path — drop the './' prefix.`);
|
|
1004
|
-
}
|
|
1005
|
-
if (absolute && segments.includes("..")) throw new IncantoError("BAD_NODE_PATH", `Invalid node path '${path}'. Absolute paths must not contain '..'.`);
|
|
1006
|
-
return {
|
|
1007
|
-
kind: absolute ? "absolute" : "relative",
|
|
1008
|
-
segments
|
|
1009
|
-
};
|
|
1010
|
-
}
|
|
1011
|
-
//#endregion
|
|
1012
1048
|
//#region src/core/node.ts
|
|
1013
1049
|
function validateName(name) {
|
|
1014
1050
|
if (name === "" || name.includes("/") || name.includes("%")) throw new IncantoError("TREE_VIOLATION", `Invalid node name '${name}'. Names must be non-empty and must not contain '/' or '%'.`);
|
|
@@ -2030,4 +2066,4 @@ function validateUniqueUids(root) {
|
|
|
2030
2066
|
walk(root);
|
|
2031
2067
|
}
|
|
2032
2068
|
//#endregion
|
|
2033
|
-
export { registerBehavior as A,
|
|
2069
|
+
export { registerBehavior as A, diagnose as C, behaviorSignals as D, behaviorSchema as E, Signal as M, clearBehaviors as O, InputMap as S, Behavior as T, savesWithoutUid as _, SCENE_FORMAT as a, effectiveOrder as b, SceneTree as c, resolveConstants as d, Node as f, restoreBehaviors as g, captureBehaviors as h, serializeNode as i, registeredBehaviors as j, getBehavior as k, CONST_REF_KEY as l, behaviorsWithoutSave as m, loadScene as n, computeViewport as o, SaveSlots as p, Scene as r, resolveViewport as s, buildNodeJson as t, isConstRef as u, createSaveStore as v, parseNodePath as w, resolveOrderGroups as x, ORDER_GROUP_BASE as y };
|
|
Binary file
|