incanto 0.59.0 → 0.61.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/bin/incanto-check.mjs +58 -4
- package/dist/2d.d.ts +22 -3
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +5 -5
- package/dist/3d.js +5 -4
- package/dist/{pathfinding-BqWBb0kh.d.ts → audio-player-D5GJgb_x.d.ts} +103 -38
- package/dist/{behavior-DWKTUzKI.d.ts → behavior-DsgayMsH.d.ts} +79 -1
- package/dist/{create-game-CHDLDQsQ.js → create-game-DH7JI5xx.js} +76 -11
- package/dist/{create-game-BiW8Men_.js → create-game-IX5lEH0P.js} +21 -294
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +1 -1
- package/dist/{duplicate-DJQd44CD.js → duplicate-CGqAmK2h.js} +1 -1
- package/dist/editor.js +2 -1
- package/dist/{environment-presets-DRAz5EV9.js → environment-presets-CNxCuhZF.js} +48 -13
- package/dist/{gameplay-BBEjPFsR.js → gameplay-Dtzd2itW.js} +53 -11
- package/dist/gameplay.d.ts +1 -1
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +23 -6
- package/dist/index.js +7 -7
- package/dist/{loader-D8n7TU8W.js → loader-D7jTvDQv.js} +797 -2
- package/dist/{loader-TvkRFbyL.d.ts → loader-DolLJWJn.d.ts} +13 -1
- package/dist/net.d.ts +2 -2
- package/dist/net.js +1 -1
- package/dist/pathfinding-_fGrCFmH.d.ts +28 -0
- package/dist/{physics-2d-BaRSRrrZ.js → physics-2d-CBnor8Zf.js} +2 -2
- package/dist/{physics-3d-CYxjh-HW.js → physics-3d-BTUfUSWO.js} +3 -3
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-BpFcgdcL.js → register-DL3izw8j.js} +46 -9
- package/dist/{register-CDrAQqPp.js → register-xuSRyD6b.js} +119 -21
- package/dist/{registry-WWcQcfMr.js → registry-CF70EArN.js} +55 -3
- package/dist/{replay-O-yAGM76.d.ts → replay-C5x2vPF5.d.ts} +16 -3
- package/dist/{replay-CEPyQtF_.js → replay-D7-yle3s.js} +56 -205
- package/dist/{split-screen-DDMZutQ6.js → split-screen-5Ban4q4n.js} +3 -3
- package/dist/{split-screen-BQ3tAsf-.d.ts → split-screen-D7OopelJ.d.ts} +2 -2
- package/dist/{src-CY21B462.js → src-DozXvyZS.js} +1 -1
- package/dist/{teardown-RApWnM1G.js → teardown-B6rwJOyS.js} +1 -1
- package/dist/{test-DHYuFyAu.js → test-Dch_7VQD.js} +19 -14
- package/dist/test.d.ts +24 -4
- package/dist/test.js +2 -2
- package/dist/vite.js +2 -2
- package/editor/assets/{agent8-BoRGtVxK.js → agent8-CF1JL2tR.js} +1 -1
- package/editor/assets/{debug-CzdyCg75.js → debug-3QzYhOPA.js} +1 -1
- package/editor/assets/{index-VesuVEhe.js → index-CAD2c5ug.js} +92 -92
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +4 -0
- package/skills/incanto-3d-models.md +1 -1
- package/skills/incanto-assets.md +10 -1
- package/skills/incanto-audio.md +21 -13
- package/skills/incanto-behaviors-and-scripts.md +7 -3
- package/skills/incanto-building-2d-games.md +12 -3
- package/skills/incanto-editor.md +1 -1
- package/skills/incanto-gameplay-behaviors.md +24 -1
- package/skills/incanto-hud.md +5 -3
- package/skills/incanto-localization.md +31 -0
- package/skills/incanto-node-reference.md +1 -0
- package/skills/incanto-scene-json-authoring.md +6 -1
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
- package/dist/particle-sim-C5OfBbmU.d.ts +0 -77
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import {
|
|
3
|
-
import { S as qualityRendering, _ as Engine, b as qualityCaps, g as AudioPlayer } from "./register-
|
|
2
|
+
import { c as parseEnvironment3D, k as diagnose, n as loadScene, s as horizonColorFromSky, u as sunDirectionFromSky, z as registerBehavior } from "./loader-D7jTvDQv.js";
|
|
3
|
+
import { S as qualityRendering, _ as Engine, b as qualityCaps, g as AudioPlayer } from "./register-xuSRyD6b.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
5
|
import { i as resolveRendering, n as attachTouchControls } from "./touch-DESwnpOc.js";
|
|
6
|
-
import { a as openBundledEditor, c as claimCanvasGestures, i as devServerLibrary, l as audioErrors, n as pauseWhenHidden, o as poseFromRenderer, r as crossFade, s as wireDevChannel, t as teardown } from "./teardown-
|
|
6
|
+
import { a as openBundledEditor, c as claimCanvasGestures, i as devServerLibrary, l as audioErrors, n as pauseWhenHidden, o as poseFromRenderer, r as crossFade, s as wireDevChannel, t as teardown } from "./teardown-B6rwJOyS.js";
|
|
7
7
|
import { o as frameStats } from "./frame-report-BSMny7oe.js";
|
|
8
|
-
import { R as PhysicsBody3D, U as createCausticsQuad, V as Node3D, n as registerGameplayBehaviors } from "./gameplay-
|
|
8
|
+
import { R as PhysicsBody3D, U as createCausticsQuad, V as Node3D, n as registerGameplayBehaviors } from "./gameplay-Dtzd2itW.js";
|
|
9
9
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
10
|
-
import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-
|
|
11
|
-
import { n as enablePhysics3D } from "./physics-3d-
|
|
10
|
+
import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-CNxCuhZF.js";
|
|
11
|
+
import { n as enablePhysics3D } from "./physics-3d-BTUfUSWO.js";
|
|
12
12
|
import { ACESFilmicToneMapping, AmbientLight, Box3, BufferAttribute, BufferGeometry, Color, DepthTexture, EquirectangularReflectionMapping, FloatType, Fog, HalfFloatType, LineBasicMaterial, LineSegments, Matrix4, Mesh, PCFShadowMap, PMREMGenerator, PerspectiveCamera, PlaneGeometry, Quaternion, Raycaster, Scene, ShaderMaterial, Vector2, Vector3, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
13
13
|
import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
|
|
14
14
|
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -125,6 +125,10 @@ var AssetStore3D = class {
|
|
|
125
125
|
} else entry.scene = gltf.scene;
|
|
126
126
|
entry.animations = gltf.animations ?? [];
|
|
127
127
|
entry.status = "ready";
|
|
128
|
+
if (!hasAnyMesh(entry.scene)) {
|
|
129
|
+
entry.error = "loaded, but it contains no meshes — this is an animation-only GLB. A clip file belongs in `animation`, not `model`.";
|
|
130
|
+
diagnose(this.engine, "error", `incanto: '${url}' ${entry.error}`);
|
|
131
|
+
}
|
|
128
132
|
}, void 0, (error) => {
|
|
129
133
|
entry.status = "error";
|
|
130
134
|
entry.error = error instanceof Error ? error.message : String(error);
|
|
@@ -172,6 +176,16 @@ var AssetStore3D = class {
|
|
|
172
176
|
this.animations.clear();
|
|
173
177
|
}
|
|
174
178
|
};
|
|
179
|
+
/** Does this loaded scene graph contain anything that will actually draw? */
|
|
180
|
+
function hasAnyMesh(scene) {
|
|
181
|
+
const walk = scene?.traverse;
|
|
182
|
+
if (!walk) return true;
|
|
183
|
+
let found = false;
|
|
184
|
+
walk.call(scene, (o) => {
|
|
185
|
+
if (o.isMesh) found = true;
|
|
186
|
+
});
|
|
187
|
+
return found;
|
|
188
|
+
}
|
|
175
189
|
//#endregion
|
|
176
190
|
//#region src/core/yield-frame.ts
|
|
177
191
|
/**
|
|
@@ -226,293 +240,6 @@ function yieldToFrame(maxWaitMs = DEFAULT_MAX_WAIT_MS, raf = typeof requestAnima
|
|
|
226
240
|
});
|
|
227
241
|
}
|
|
228
242
|
//#endregion
|
|
229
|
-
//#region src/3d/environment.ts
|
|
230
|
-
const SKY_KEYS = [
|
|
231
|
-
"type",
|
|
232
|
-
"sunPosition",
|
|
233
|
-
"elevationDeg",
|
|
234
|
-
"azimuthDeg",
|
|
235
|
-
"turbidity",
|
|
236
|
-
"rayleigh"
|
|
237
|
-
];
|
|
238
|
-
const FOG_KEYS = [
|
|
239
|
-
"color",
|
|
240
|
-
"near",
|
|
241
|
-
"far"
|
|
242
|
-
];
|
|
243
|
-
const CLOUD_KEYS = [
|
|
244
|
-
"coverage",
|
|
245
|
-
"density",
|
|
246
|
-
"base",
|
|
247
|
-
"top",
|
|
248
|
-
"color",
|
|
249
|
-
"shadeColor",
|
|
250
|
-
"speed",
|
|
251
|
-
"scale"
|
|
252
|
-
];
|
|
253
|
-
const BLOOM_KEYS = ["threshold", "strength"];
|
|
254
|
-
const POST_KEYS = [
|
|
255
|
-
"vignette",
|
|
256
|
-
"saturation",
|
|
257
|
-
"contrast"
|
|
258
|
-
];
|
|
259
|
-
const SHADOW_KEYS = [
|
|
260
|
-
"mapSize",
|
|
261
|
-
"radius",
|
|
262
|
-
"static"
|
|
263
|
-
];
|
|
264
|
-
const SHADOW_MAP_SIZES = [1024, 2048];
|
|
265
|
-
const DEFAULT_TURBIDITY = 2;
|
|
266
|
-
const DEFAULT_RAYLEIGH = 1;
|
|
267
|
-
const DEFAULT_FOG_NEAR = 50;
|
|
268
|
-
const DEFAULT_FOG_FAR = 800;
|
|
269
|
-
/** Fallback haze when fog is declared without a sky to derive a horizon from. */
|
|
270
|
-
const DEFAULT_FOG_COLOR = "#cfd8e0";
|
|
271
|
-
const DEG2RAD = Math.PI / 180;
|
|
272
|
-
/** Parse + hard-validate the 3D slice of a scene's `environment` header. */
|
|
273
|
-
function parseEnvironment3D(env) {
|
|
274
|
-
return {
|
|
275
|
-
exposure: parseExposure(env?.exposure),
|
|
276
|
-
sky: parseSky(env?.sky),
|
|
277
|
-
fog: parseFog(env?.fog, env?.sky !== void 0),
|
|
278
|
-
clouds: parseClouds(env?.clouds),
|
|
279
|
-
bloom: parseBloom(env?.bloom),
|
|
280
|
-
post: parsePost(env?.post),
|
|
281
|
-
shadows: parseShadows(env?.shadows)
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* elevation/azimuth (degrees) → unit direction. Matches three's Sky example
|
|
286
|
-
* (`Vector3.setFromSphericalCoords`): azimuth 0 = +Z, 90 = +X; elevation 90 =
|
|
287
|
-
* straight up.
|
|
288
|
-
*/
|
|
289
|
-
function sunDirectionFromElevationAzimuth(elevationDeg, azimuthDeg) {
|
|
290
|
-
const phi = (90 - elevationDeg) * DEG2RAD;
|
|
291
|
-
const theta = azimuthDeg * DEG2RAD;
|
|
292
|
-
return [
|
|
293
|
-
Math.sin(phi) * Math.sin(theta),
|
|
294
|
-
Math.cos(phi),
|
|
295
|
-
Math.sin(phi) * Math.cos(theta)
|
|
296
|
-
];
|
|
297
|
-
}
|
|
298
|
-
/** The sky's sun as a UNIT vector — what Water3D/Foliage3D uniforms consume. */
|
|
299
|
-
function sunDirectionFromSky(sky) {
|
|
300
|
-
const [x, y, z] = sky.sunPosition;
|
|
301
|
-
const len = Math.hypot(x, y, z) || 1;
|
|
302
|
-
return [
|
|
303
|
-
x / len,
|
|
304
|
-
y / len,
|
|
305
|
-
z / len
|
|
306
|
-
];
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* A horizon-ish haze color derived from the sky config — the default fog
|
|
310
|
-
* color. Cheap model, judged by eye: clear skies haze blue-grey, turbid skies
|
|
311
|
-
* whiten, and a low sun warms the band toward amber.
|
|
312
|
-
*/
|
|
313
|
-
function horizonColorFromSky(sky) {
|
|
314
|
-
const clear = [
|
|
315
|
-
191,
|
|
316
|
-
213,
|
|
317
|
-
232
|
|
318
|
-
];
|
|
319
|
-
const hazy = [
|
|
320
|
-
233,
|
|
321
|
-
228,
|
|
322
|
-
217
|
|
323
|
-
];
|
|
324
|
-
const warm = [
|
|
325
|
-
242,
|
|
326
|
-
201,
|
|
327
|
-
150
|
|
328
|
-
];
|
|
329
|
-
const t = clamp01((sky.turbidity - DEFAULT_TURBIDITY) / 8);
|
|
330
|
-
const dir = sunDirectionFromSky(sky);
|
|
331
|
-
const w = clamp01((18 - Math.asin(clamp(dir[1], -1, 1)) / DEG2RAD) / 18) * .8;
|
|
332
|
-
const mix = (i) => Math.round(lerp(lerp(clear[i], hazy[i], t), warm[i], w));
|
|
333
|
-
return `#${[
|
|
334
|
-
mix(0),
|
|
335
|
-
mix(1),
|
|
336
|
-
mix(2)
|
|
337
|
-
].map((c) => c.toString(16).padStart(2, "0")).join("")}`;
|
|
338
|
-
}
|
|
339
|
-
function parseExposure(value) {
|
|
340
|
-
if (value === void 0) return 1;
|
|
341
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) throw new IncantoError("BAD_FORMAT", `environment.exposure must be a finite number > 0 (tone-mapping exposure, default 1), got ${JSON.stringify(value)}.`, { prop: "exposure" });
|
|
342
|
-
return value;
|
|
343
|
-
}
|
|
344
|
-
function parseSky(value) {
|
|
345
|
-
if (value === void 0) return null;
|
|
346
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new IncantoError("BAD_FORMAT", `environment.sky must be an object ({ type?: "atmosphere", sunPosition? | elevationDeg?+azimuthDeg?, turbidity?, rayleigh? }), got ${JSON.stringify(value)}.`, { prop: "sky" });
|
|
347
|
-
const sky = value;
|
|
348
|
-
for (const key of Object.keys(sky)) if (!SKY_KEYS.includes(key)) throw new IncantoError("BAD_FORMAT", `environment.sky has unknown key '${key}'. Valid keys: [${SKY_KEYS.join(", ")}].`, {
|
|
349
|
-
prop: "sky",
|
|
350
|
-
validOptions: SKY_KEYS
|
|
351
|
-
});
|
|
352
|
-
if (sky.type !== void 0 && sky.type !== "atmosphere") throw new IncantoError("BAD_FORMAT", `environment.sky.type must be 'atmosphere' (the only sky type so far), got ${JSON.stringify(sky.type)}.`, {
|
|
353
|
-
prop: "sky",
|
|
354
|
-
validOptions: ["atmosphere"]
|
|
355
|
-
});
|
|
356
|
-
const hasAngles = sky.elevationDeg !== void 0 || sky.azimuthDeg !== void 0;
|
|
357
|
-
if (sky.sunPosition !== void 0 && hasAngles) throw new IncantoError("BAD_FORMAT", `environment.sky takes sunPosition OR elevationDeg/azimuthDeg, not both.`, {
|
|
358
|
-
prop: "sky",
|
|
359
|
-
validOptions: ["sunPosition", "elevationDeg+azimuthDeg"]
|
|
360
|
-
});
|
|
361
|
-
let sunPosition;
|
|
362
|
-
if (sky.sunPosition !== void 0) {
|
|
363
|
-
const sp = sky.sunPosition;
|
|
364
|
-
if (!Array.isArray(sp) || sp.length !== 3 || !sp.every((v) => typeof v === "number" && Number.isFinite(v)) || Math.hypot(sp[0], sp[1], sp[2]) === 0) throw new IncantoError("BAD_FORMAT", `environment.sky.sunPosition must be a non-zero [x, y, z] vector, got ${JSON.stringify(sp)}.`, { prop: "sky" });
|
|
365
|
-
sunPosition = [
|
|
366
|
-
sp[0],
|
|
367
|
-
sp[1],
|
|
368
|
-
sp[2]
|
|
369
|
-
];
|
|
370
|
-
} else {
|
|
371
|
-
const elevation = numberOr(sky.elevationDeg, 32, "sky.elevationDeg");
|
|
372
|
-
const azimuth = numberOr(sky.azimuthDeg, 135, "sky.azimuthDeg");
|
|
373
|
-
if (elevation < -90 || elevation > 90) throw new IncantoError("BAD_FORMAT", `environment.sky.elevationDeg must be in [-90, 90] (degrees above the horizon), got ${elevation}.`, { prop: "sky" });
|
|
374
|
-
sunPosition = sunDirectionFromElevationAzimuth(elevation, azimuth);
|
|
375
|
-
}
|
|
376
|
-
const turbidity = numberOr(sky.turbidity, DEFAULT_TURBIDITY, "sky.turbidity");
|
|
377
|
-
if (turbidity <= 0) throw new IncantoError("BAD_FORMAT", `environment.sky.turbidity must be > 0 (atmospheric haze; 2 ≈ clear day), got ${turbidity}.`, { prop: "sky" });
|
|
378
|
-
const rayleigh = numberOr(sky.rayleigh, DEFAULT_RAYLEIGH, "sky.rayleigh");
|
|
379
|
-
if (rayleigh < 0) throw new IncantoError("BAD_FORMAT", `environment.sky.rayleigh must be >= 0 (Rayleigh scattering; 1 ≈ earth-like), got ${rayleigh}.`, { prop: "sky" });
|
|
380
|
-
return {
|
|
381
|
-
sunPosition,
|
|
382
|
-
turbidity,
|
|
383
|
-
rayleigh
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
function parseFog(value, hasSky) {
|
|
387
|
-
if (value === void 0) return null;
|
|
388
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new IncantoError("BAD_FORMAT", `environment.fog must be an object ({ color?, near?, far? }), got ${JSON.stringify(value)}.`, { prop: "fog" });
|
|
389
|
-
const fog = value;
|
|
390
|
-
for (const key of Object.keys(fog)) if (!FOG_KEYS.includes(key)) throw new IncantoError("BAD_FORMAT", `environment.fog has unknown key '${key}'. Valid keys: [${FOG_KEYS.join(", ")}].`, {
|
|
391
|
-
prop: "fog",
|
|
392
|
-
validOptions: FOG_KEYS
|
|
393
|
-
});
|
|
394
|
-
if (fog.color !== void 0 && typeof fog.color !== "string") throw new IncantoError("BAD_FORMAT", `environment.fog.color must be a hex color string, got ${JSON.stringify(fog.color)}.`, { prop: "fog" });
|
|
395
|
-
const near = numberOr(fog.near, DEFAULT_FOG_NEAR, "fog.near");
|
|
396
|
-
const far = numberOr(fog.far, DEFAULT_FOG_FAR, "fog.far");
|
|
397
|
-
if (near < 0) throw new IncantoError("BAD_FORMAT", `environment.fog.near must be >= 0 meters, got ${near}.`, { prop: "fog" });
|
|
398
|
-
if (far <= near) throw new IncantoError("BAD_FORMAT", `environment.fog.far must be > near (got near ${near}, far ${far}).`, { prop: "fog" });
|
|
399
|
-
return {
|
|
400
|
-
color: fog.color ?? (hasSky ? "" : DEFAULT_FOG_COLOR),
|
|
401
|
-
near,
|
|
402
|
-
far
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
function parseClouds(value) {
|
|
406
|
-
if (value === void 0) return null;
|
|
407
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new IncantoError("BAD_FORMAT", `environment.clouds must be an object ({ coverage?, density?, base?, top?, color?, shadeColor?, speed?, scale? }), got ${JSON.stringify(value)}.`, { prop: "clouds" });
|
|
408
|
-
const c = value;
|
|
409
|
-
for (const key of Object.keys(c)) if (!CLOUD_KEYS.includes(key)) throw new IncantoError("BAD_FORMAT", `environment.clouds has unknown key '${key}'. Valid keys: [${CLOUD_KEYS.join(", ")}].`, {
|
|
410
|
-
prop: "clouds",
|
|
411
|
-
validOptions: CLOUD_KEYS
|
|
412
|
-
});
|
|
413
|
-
for (const k of ["color", "shadeColor"]) if (c[k] !== void 0 && typeof c[k] !== "string") throw new IncantoError("BAD_FORMAT", `environment.clouds.${k} must be a hex color string, got ${JSON.stringify(c[k])}.`, { prop: "clouds" });
|
|
414
|
-
const coverage = numberOr(c.coverage, .5, "clouds.coverage");
|
|
415
|
-
if (coverage < 0 || coverage > 1) throw new IncantoError("BAD_FORMAT", `environment.clouds.coverage must be in [0, 1] (how much sky is cloudy), got ${coverage}.`, { prop: "clouds" });
|
|
416
|
-
const density = numberOr(c.density, 1, "clouds.density");
|
|
417
|
-
if (density < 0) throw new IncantoError("BAD_FORMAT", `environment.clouds.density must be >= 0 (optical thickness), got ${density}.`, { prop: "clouds" });
|
|
418
|
-
const base = numberOr(c.base, 120, "clouds.base");
|
|
419
|
-
const top = numberOr(c.top, 320, "clouds.top");
|
|
420
|
-
if (top <= base) throw new IncantoError("BAD_FORMAT", `environment.clouds.top must be > base (got base ${base}, top ${top}).`, { prop: "clouds" });
|
|
421
|
-
const speed = numberOr(c.speed, 1, "clouds.speed");
|
|
422
|
-
const scale = numberOr(c.scale, 240, "clouds.scale");
|
|
423
|
-
if (scale <= 0) throw new IncantoError("BAD_FORMAT", `environment.clouds.scale must be > 0 (feature size in world units), got ${scale}.`, { prop: "clouds" });
|
|
424
|
-
return {
|
|
425
|
-
coverage,
|
|
426
|
-
density,
|
|
427
|
-
base,
|
|
428
|
-
top,
|
|
429
|
-
color: c.color ?? "#ffffff",
|
|
430
|
-
shadeColor: c.shadeColor ?? "#9fb0c8",
|
|
431
|
-
speed,
|
|
432
|
-
scale
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
function parseBloom(value) {
|
|
436
|
-
if (value === void 0) return null;
|
|
437
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new IncantoError("BAD_FORMAT", `environment.bloom must be an object ({ threshold?, strength? }), got ${JSON.stringify(value)}.`, { prop: "bloom" });
|
|
438
|
-
const b = value;
|
|
439
|
-
for (const key of Object.keys(b)) if (!BLOOM_KEYS.includes(key)) throw new IncantoError("BAD_FORMAT", `environment.bloom has unknown key '${key}'. Valid keys: [${BLOOM_KEYS.join(", ")}].`, {
|
|
440
|
-
prop: "bloom",
|
|
441
|
-
validOptions: BLOOM_KEYS
|
|
442
|
-
});
|
|
443
|
-
const threshold = numberOr(b.threshold, 1, "bloom.threshold");
|
|
444
|
-
if (threshold < 0 || threshold > 8) throw new IncantoError("BAD_FORMAT", `environment.bloom.threshold must be in [0, 8] (linear-HDR luminance; 1 = white), got ${threshold}.`, { prop: "bloom" });
|
|
445
|
-
const strength = numberOr(b.strength, .8, "bloom.strength");
|
|
446
|
-
if (strength < 0) throw new IncantoError("BAD_FORMAT", `environment.bloom.strength must be >= 0, got ${strength}.`, { prop: "bloom" });
|
|
447
|
-
return {
|
|
448
|
-
threshold,
|
|
449
|
-
strength
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
function parsePost(value) {
|
|
453
|
-
if (value === void 0) return null;
|
|
454
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new IncantoError("BAD_FORMAT", `environment.post must be an object ({ vignette?, saturation?, contrast? }), got ${JSON.stringify(value)}.`, { prop: "post" });
|
|
455
|
-
const p = value;
|
|
456
|
-
for (const key of Object.keys(p)) if (!POST_KEYS.includes(key)) throw new IncantoError("BAD_FORMAT", `environment.post has unknown key '${key}'. Valid keys: [${POST_KEYS.join(", ")}].`, {
|
|
457
|
-
prop: "post",
|
|
458
|
-
validOptions: POST_KEYS
|
|
459
|
-
});
|
|
460
|
-
const vignette = numberOr(p.vignette, 0, "post.vignette");
|
|
461
|
-
if (vignette < 0 || vignette > 1) throw new IncantoError("BAD_FORMAT", `environment.post.vignette must be in [0, 1], got ${vignette}.`, { prop: "post" });
|
|
462
|
-
const saturation = numberOr(p.saturation, 1, "post.saturation");
|
|
463
|
-
if (saturation < 0 || saturation > 4) throw new IncantoError("BAD_FORMAT", `environment.post.saturation must be in [0, 4] (1 = neutral), got ${saturation}.`, { prop: "post" });
|
|
464
|
-
const contrast = numberOr(p.contrast, 1, "post.contrast");
|
|
465
|
-
if (contrast < .2 || contrast > 3) throw new IncantoError("BAD_FORMAT", `environment.post.contrast must be in [0.2, 3] (1 = neutral), got ${contrast}.`, { prop: "post" });
|
|
466
|
-
return {
|
|
467
|
-
vignette,
|
|
468
|
-
saturation,
|
|
469
|
-
contrast
|
|
470
|
-
};
|
|
471
|
-
}
|
|
472
|
-
function parseShadows(value) {
|
|
473
|
-
if (value === void 0) return null;
|
|
474
|
-
if (value === false) return false;
|
|
475
|
-
if (value === true) return {
|
|
476
|
-
mapSize: 2048,
|
|
477
|
-
radius: 1,
|
|
478
|
-
static: false
|
|
479
|
-
};
|
|
480
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new IncantoError("BAD_FORMAT", `environment.shadows must be true, false or an object ({ mapSize?, radius? }), got ${JSON.stringify(value)}.`, { prop: "shadows" });
|
|
481
|
-
const shadows = value;
|
|
482
|
-
for (const key of Object.keys(shadows)) if (!SHADOW_KEYS.includes(key)) throw new IncantoError("BAD_FORMAT", `environment.shadows has unknown key '${key}'. Valid keys: [${SHADOW_KEYS.join(", ")}].`, {
|
|
483
|
-
prop: "shadows",
|
|
484
|
-
validOptions: SHADOW_KEYS
|
|
485
|
-
});
|
|
486
|
-
const mapSize = shadows.mapSize === void 0 ? 2048 : shadows.mapSize;
|
|
487
|
-
if (!SHADOW_MAP_SIZES.includes(mapSize)) throw new IncantoError("BAD_FORMAT", `environment.shadows.mapSize must be one of [${SHADOW_MAP_SIZES.join(", ")}], got ${JSON.stringify(shadows.mapSize)}.`, {
|
|
488
|
-
prop: "shadows",
|
|
489
|
-
validOptions: SHADOW_MAP_SIZES.map(String)
|
|
490
|
-
});
|
|
491
|
-
const radius = numberOr(shadows.radius, 1, "shadows.radius");
|
|
492
|
-
if (radius < 0) throw new IncantoError("BAD_FORMAT", `environment.shadows.radius must be >= 0, got ${radius}.`, { prop: "shadows" });
|
|
493
|
-
const staticShadows = shadows.static === void 0 ? false : shadows.static;
|
|
494
|
-
if (typeof staticShadows !== "boolean") throw new IncantoError("BAD_FORMAT", `environment.shadows.static must be a boolean, got ${JSON.stringify(shadows.static)}.`, { prop: "shadows" });
|
|
495
|
-
return {
|
|
496
|
-
mapSize,
|
|
497
|
-
radius,
|
|
498
|
-
static: staticShadows
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
function numberOr(value, fallback, at) {
|
|
502
|
-
if (value === void 0) return fallback;
|
|
503
|
-
if (typeof value !== "number" || !Number.isFinite(value)) throw new IncantoError("BAD_FORMAT", `environment.${at} must be a finite number, got ${JSON.stringify(value)}.`, { prop: at });
|
|
504
|
-
return value;
|
|
505
|
-
}
|
|
506
|
-
function clamp(v, min, max) {
|
|
507
|
-
return Math.min(Math.max(v, min), max);
|
|
508
|
-
}
|
|
509
|
-
function clamp01(v) {
|
|
510
|
-
return clamp(v, 0, 1);
|
|
511
|
-
}
|
|
512
|
-
function lerp(a, b, t) {
|
|
513
|
-
return a + (b - a) * t;
|
|
514
|
-
}
|
|
515
|
-
//#endregion
|
|
516
243
|
//#region src/3d/environment-runtime.ts
|
|
517
244
|
/**
|
|
518
245
|
* Live environment editing — the renderer re-applies `scene.environment`
|
|
@@ -2666,4 +2393,4 @@ function wireAudioUnlock(engine, root, canvas) {
|
|
|
2666
2393
|
return detachAll;
|
|
2667
2394
|
}
|
|
2668
2395
|
//#endregion
|
|
2669
|
-
export { Environment3D as a,
|
|
2396
|
+
export { Environment3D as a, syncTree as i, create_game_exports as n, setEnvironment3D as o, Renderer3D as r, AssetStore3D as s, createGame3D as t };
|
package/dist/debug.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ft as LogLevel, T as RendererStats, b as Engine } from "./behavior-DsgayMsH.js";
|
|
2
2
|
|
|
3
3
|
//#region src/debug/panel.d.ts
|
|
4
4
|
/** Minimal document surface the overlay needs (injectable for tests). */
|
package/dist/debug.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as jsonClone } from "./json-CwwhxQgb.js";
|
|
2
|
-
import { s as mergeStaticProps } from "./registry-
|
|
2
|
+
import { s as mergeStaticProps } from "./registry-CF70EArN.js";
|
|
3
3
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
4
4
|
//#region src/debug/capture.ts
|
|
5
5
|
/**
|
package/dist/editor.js
CHANGED
|
@@ -2372,7 +2372,8 @@ function Bn(e, t, n) {
|
|
|
2372
2372
|
var Vn = [
|
|
2373
2373
|
"connections",
|
|
2374
2374
|
"input",
|
|
2375
|
-
"multiplayer"
|
|
2375
|
+
"multiplayer",
|
|
2376
|
+
"strings"
|
|
2376
2377
|
];
|
|
2377
2378
|
function Hn(e, t, n) {
|
|
2378
2379
|
e.appendChild(Tr("scene")), e.appendChild(Ar("name", String(t.working.name ?? ""), (e) => {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { I as translateOn, t as registerCoreNodes } from "./register-
|
|
1
|
+
import { k as diagnose } from "./loader-D7jTvDQv.js";
|
|
2
|
+
import { I as translateOn, t as registerCoreNodes } from "./register-xuSRyD6b.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
5
|
-
import { i as getNodeSchema, l as registerNode } from "./registry-
|
|
5
|
+
import { i as getNodeSchema, l as registerNode } from "./registry-CF70EArN.js";
|
|
6
6
|
import { t as createNoise2D } from "./noise-CGUMx44x.js";
|
|
7
7
|
import { i as ParticleSim, n as resolveFrames, o as PARTICLE_PRESET_NAMES, r as validateAnimationAliases, s as applyParticlePreset, t as resolveAnimation } from "./sprite-animation-CY-mrr1L.js";
|
|
8
|
-
import { B as StaticBody3D, F as WaterCutout3D, G as colliderFootDrop, I as Area3D, L as CharacterBody3D, N as Water3D, R as PhysicsBody3D, V as Node3D, w as tolerateUnknownAction, z as RigidBody3D } from "./gameplay-
|
|
8
|
+
import { B as StaticBody3D, F as WaterCutout3D, G as colliderFootDrop, I as Area3D, L as CharacterBody3D, N as Water3D, R as PhysicsBody3D, V as Node3D, w as tolerateUnknownAction, z as RigidBody3D } from "./gameplay-Dtzd2itW.js";
|
|
9
9
|
import { t as checkSheetGrid } from "./sheet-grid-BT6N_Bjs.js";
|
|
10
10
|
import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
|
|
11
11
|
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";
|
|
@@ -727,7 +727,8 @@ var Joint3D = class extends Node3D {
|
|
|
727
727
|
},
|
|
728
728
|
target: {
|
|
729
729
|
default: "",
|
|
730
|
-
nodePath: true
|
|
730
|
+
nodePath: true,
|
|
731
|
+
required: true
|
|
731
732
|
},
|
|
732
733
|
anchor: { default: [
|
|
733
734
|
0,
|
|
@@ -2335,7 +2336,8 @@ var BoneAttachment3D = class extends Node3D {
|
|
|
2335
2336
|
/** Node path to the ModelInstance3D whose skeleton to ride. */
|
|
2336
2337
|
target: {
|
|
2337
2338
|
default: "",
|
|
2338
|
-
nodePath: true
|
|
2339
|
+
nodePath: true,
|
|
2340
|
+
required: true
|
|
2339
2341
|
},
|
|
2340
2342
|
/** Bone name ("RightHand", "Head", …). Empty = inert. */
|
|
2341
2343
|
bone: { default: "" }
|
|
@@ -2428,7 +2430,8 @@ var BoneLookAt3D = class extends Node3D {
|
|
|
2428
2430
|
/** Node path to the ModelInstance3D whose bone to steer. */
|
|
2429
2431
|
target: {
|
|
2430
2432
|
default: "",
|
|
2431
|
-
nodePath: true
|
|
2433
|
+
nodePath: true,
|
|
2434
|
+
required: true
|
|
2432
2435
|
},
|
|
2433
2436
|
/** Bone name ("Head", "Neck", "Spine2" — Mixamo spellings matched). */
|
|
2434
2437
|
bone: { default: "Head" },
|
|
@@ -2440,7 +2443,13 @@ var BoneLookAt3D = class extends Node3D {
|
|
|
2440
2443
|
/** Comfort cone half-angle, degrees — beyond it the head returns to the anim. */
|
|
2441
2444
|
maxAngleDeg: { default: 75 },
|
|
2442
2445
|
/** Blend weight 0..1 (how far toward the target the bone turns). */
|
|
2443
|
-
weight: {
|
|
2446
|
+
weight: {
|
|
2447
|
+
default: .85,
|
|
2448
|
+
range: {
|
|
2449
|
+
min: 0,
|
|
2450
|
+
max: 1
|
|
2451
|
+
}
|
|
2452
|
+
},
|
|
2444
2453
|
/** The bone's local facing axis. */
|
|
2445
2454
|
forwardAxis: {
|
|
2446
2455
|
default: "+z",
|
|
@@ -6449,9 +6458,21 @@ var ModelInstance3D = class extends Node3D {
|
|
|
6449
6458
|
static signals = ["animationFinished"];
|
|
6450
6459
|
static props = {
|
|
6451
6460
|
...Node3D.props,
|
|
6452
|
-
model: {
|
|
6453
|
-
|
|
6454
|
-
|
|
6461
|
+
model: {
|
|
6462
|
+
default: "",
|
|
6463
|
+
asset: {
|
|
6464
|
+
kind: "model",
|
|
6465
|
+
refOnly: true
|
|
6466
|
+
}
|
|
6467
|
+
},
|
|
6468
|
+
animation: {
|
|
6469
|
+
default: "",
|
|
6470
|
+
asset: { kind: "animation" }
|
|
6471
|
+
},
|
|
6472
|
+
targetHeight: {
|
|
6473
|
+
default: 0,
|
|
6474
|
+
range: { min: 0 }
|
|
6475
|
+
},
|
|
6455
6476
|
castShadow: { default: false },
|
|
6456
6477
|
animationLoop: { default: true },
|
|
6457
6478
|
/** Playback rate: 1 = authored speed, 0.5 = half, 2 = double. */
|
|
@@ -6466,8 +6487,22 @@ var ModelInstance3D = class extends Node3D {
|
|
|
6466
6487
|
upperBodyRoot: { default: "Spine" },
|
|
6467
6488
|
receiveShadow: { default: false },
|
|
6468
6489
|
tint: { default: "" },
|
|
6469
|
-
metalness: {
|
|
6470
|
-
|
|
6490
|
+
metalness: {
|
|
6491
|
+
default: -1,
|
|
6492
|
+
range: {
|
|
6493
|
+
min: 0,
|
|
6494
|
+
max: 1,
|
|
6495
|
+
allow: [-1]
|
|
6496
|
+
}
|
|
6497
|
+
},
|
|
6498
|
+
roughness: {
|
|
6499
|
+
default: -1,
|
|
6500
|
+
range: {
|
|
6501
|
+
min: 0,
|
|
6502
|
+
max: 1,
|
|
6503
|
+
allow: [-1]
|
|
6504
|
+
}
|
|
6505
|
+
}
|
|
6471
6506
|
};
|
|
6472
6507
|
model = "";
|
|
6473
6508
|
animation = "";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { O as Node, P as Behavior, _ as SaveSlots, k as diagnose, n as loadScene, w as effectiveOrder, z as registerBehavior } from "./loader-D7jTvDQv.js";
|
|
2
2
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
3
3
|
import { t as jsonClone } from "./json-CwwhxQgb.js";
|
|
4
|
-
import { t as duplicateNode } from "./duplicate-
|
|
4
|
+
import { t as duplicateNode } from "./duplicate-CGqAmK2h.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();
|
|
@@ -4975,6 +4975,7 @@ var FloatAway = class extends Behavior {
|
|
|
4975
4975
|
onReady() {
|
|
4976
4976
|
const node = this.node;
|
|
4977
4977
|
this.start = [...node.position ?? []];
|
|
4978
|
+
if (node.opacity === void 0) diagnose(this.node.tree?.engine, "warn", `[incanto] FloatAway on '${this.node.getPath()}' will not fade — ${this.node.constructor.name} has no "opacity" prop, so it pops out at full brightness instead. Use a node that has one (Label, Label3D, Sprite2D, Sprite3D).`);
|
|
4978
4979
|
}
|
|
4979
4980
|
update(dt) {
|
|
4980
4981
|
if (this.done) return;
|
|
@@ -5024,9 +5025,18 @@ var FollowCamera = class extends Behavior {
|
|
|
5024
5025
|
/** Constant offset added to the target's position ([x,y] or [x,y,z]). */
|
|
5025
5026
|
offset: { default: [] },
|
|
5026
5027
|
/** 0..1 retention factor: 0 = snap, higher = smoother chase. */
|
|
5027
|
-
smoothing: {
|
|
5028
|
+
smoothing: {
|
|
5029
|
+
default: 0,
|
|
5030
|
+
range: {
|
|
5031
|
+
min: 0,
|
|
5032
|
+
max: 1
|
|
5033
|
+
}
|
|
5034
|
+
},
|
|
5028
5035
|
/** Don't move until the target is at least this far from the desired point. */
|
|
5029
|
-
deadzone: {
|
|
5036
|
+
deadzone: {
|
|
5037
|
+
default: 0,
|
|
5038
|
+
range: { min: 0 }
|
|
5039
|
+
}
|
|
5030
5040
|
};
|
|
5031
5041
|
static signals = [];
|
|
5032
5042
|
target = "";
|
|
@@ -5109,7 +5119,6 @@ function tolerateUnknownAction(ctx, action, read, fallback) {
|
|
|
5109
5119
|
function restartScene(engine) {
|
|
5110
5120
|
const source = engine.scene?.source;
|
|
5111
5121
|
if (!source) return;
|
|
5112
|
-
engine.timeScale = 1;
|
|
5113
5122
|
engine.setScene(loadScene(jsonClone(source)));
|
|
5114
5123
|
}
|
|
5115
5124
|
/**
|
|
@@ -5119,7 +5128,6 @@ function restartScene(engine) {
|
|
|
5119
5128
|
function goToScene(engine, sceneJson, opts) {
|
|
5120
5129
|
const fade = opts?.fadeSeconds ?? .4;
|
|
5121
5130
|
const swap = () => {
|
|
5122
|
-
engine.timeScale = 1;
|
|
5123
5131
|
engine.setScene(loadScene(jsonClone(sceneJson)));
|
|
5124
5132
|
};
|
|
5125
5133
|
if (typeof document === "undefined" || fade <= 0) {
|
|
@@ -5500,13 +5508,14 @@ function screenFlash(engine, color = "#ffffff", opacity = .35, seconds = .25) {
|
|
|
5500
5508
|
*/
|
|
5501
5509
|
function hitStop(engine, seconds = .08) {
|
|
5502
5510
|
recordEffect(engine, "hitstop", "", "engine", seconds);
|
|
5503
|
-
const state =
|
|
5511
|
+
const state = liveHitStop(engine);
|
|
5504
5512
|
if (state) {
|
|
5505
5513
|
state.until = Math.max(state.until, engine.unscaledTime + seconds);
|
|
5506
5514
|
return;
|
|
5507
5515
|
}
|
|
5508
5516
|
const restore = engine.timeScale;
|
|
5509
5517
|
const entry = {
|
|
5518
|
+
startedAt: engine.unscaledTime,
|
|
5510
5519
|
until: engine.unscaledTime + seconds,
|
|
5511
5520
|
restore,
|
|
5512
5521
|
release: () => {}
|
|
@@ -5514,12 +5523,35 @@ function hitStop(engine, seconds = .08) {
|
|
|
5514
5523
|
hitStops.set(engine, entry);
|
|
5515
5524
|
engine.timeScale = 0;
|
|
5516
5525
|
entry.release = engine.updated.connect(() => {
|
|
5526
|
+
if (!liveHitStop(engine)) return;
|
|
5517
5527
|
if (engine.unscaledTime < entry.until) return;
|
|
5518
5528
|
engine.timeScale = entry.restore;
|
|
5519
5529
|
entry.release();
|
|
5520
5530
|
hitStops.delete(engine);
|
|
5521
5531
|
});
|
|
5522
5532
|
}
|
|
5533
|
+
/**
|
|
5534
|
+
* The engine's pending freeze, if the clock it was measured against still runs.
|
|
5535
|
+
*
|
|
5536
|
+
* `setScene` resets `unscaledTime` to 0, and a freeze deadline is an ABSOLUTE
|
|
5537
|
+
* reading of that clock — so a hit-stop taken on the killing blow, two minutes
|
|
5538
|
+
* into a level, survived the restart as a deadline two minutes in the future.
|
|
5539
|
+
* Measured: `hitStop(engine, 0.08)`, then the restart, then five real seconds
|
|
5540
|
+
* of ticks — 2.08 of them frozen, and a level that long freezes that long. The
|
|
5541
|
+
* quieter half is the next scene's OWN hit-stop: it found the stale entry,
|
|
5542
|
+
* extended a deadline nobody was waiting on, and never froze anything.
|
|
5543
|
+
*
|
|
5544
|
+
* A clock that reads earlier than the freeze began cannot be the clock the
|
|
5545
|
+
* freeze was scheduled on. `setScene` already put `timeScale` back to 1, so
|
|
5546
|
+
* there is nothing to restore — just let go.
|
|
5547
|
+
*/
|
|
5548
|
+
function liveHitStop(engine) {
|
|
5549
|
+
const entry = hitStops.get(engine);
|
|
5550
|
+
if (!entry) return void 0;
|
|
5551
|
+
if (engine.unscaledTime >= entry.startedAt) return entry;
|
|
5552
|
+
entry.release();
|
|
5553
|
+
hitStops.delete(engine);
|
|
5554
|
+
}
|
|
5523
5555
|
const hitStops = /* @__PURE__ */ new Map();
|
|
5524
5556
|
//#endregion
|
|
5525
5557
|
//#region src/gameplay/lifetime.ts
|
|
@@ -5605,7 +5637,10 @@ function ease(curve, t) {
|
|
|
5605
5637
|
var MoveTo = class extends Behavior {
|
|
5606
5638
|
static props = {
|
|
5607
5639
|
/** Destination position ([x,y] or [x,y,z]). */
|
|
5608
|
-
to: {
|
|
5640
|
+
to: {
|
|
5641
|
+
default: [],
|
|
5642
|
+
required: true
|
|
5643
|
+
},
|
|
5609
5644
|
/** Seconds the move takes. */
|
|
5610
5645
|
duration: { default: 1 },
|
|
5611
5646
|
/** Easing curve. */
|
|
@@ -5819,7 +5854,10 @@ function distanceBetween(a, b) {
|
|
|
5819
5854
|
var Patrol = class extends Behavior {
|
|
5820
5855
|
static props = {
|
|
5821
5856
|
/** Waypoints: array of position arrays OR node-path strings to read. */
|
|
5822
|
-
points: {
|
|
5857
|
+
points: {
|
|
5858
|
+
default: [],
|
|
5859
|
+
required: true
|
|
5860
|
+
},
|
|
5823
5861
|
/** Units per second along the path. */
|
|
5824
5862
|
speed: { default: 60 },
|
|
5825
5863
|
/** Wrap to the first point after the last (ignored in pingpong). */
|
|
@@ -6355,7 +6393,8 @@ var Spawner = class extends Behavior {
|
|
|
6355
6393
|
/** Node path of the template to clone. */
|
|
6356
6394
|
prefab: {
|
|
6357
6395
|
default: "",
|
|
6358
|
-
nodePath: true
|
|
6396
|
+
nodePath: true,
|
|
6397
|
+
required: true
|
|
6359
6398
|
},
|
|
6360
6399
|
/** Seconds between spawns. */
|
|
6361
6400
|
interval: { default: 1 },
|
|
@@ -6508,7 +6547,10 @@ var Wander = class extends Behavior {
|
|
|
6508
6547
|
var WaveSpawner = class extends Behavior {
|
|
6509
6548
|
static props = {
|
|
6510
6549
|
/** Array of { prefab, count, interval, delayBefore }. */
|
|
6511
|
-
waves: {
|
|
6550
|
+
waves: {
|
|
6551
|
+
default: [],
|
|
6552
|
+
required: true
|
|
6553
|
+
},
|
|
6512
6554
|
/** Begin the first wave's countdown at ready. */
|
|
6513
6555
|
autoStart: { default: true }
|
|
6514
6556
|
};
|
package/dist/gameplay.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, t as Behavior } from "./behavior-DsgayMsH.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 Health, C as restartScene, D as DayNight, E as FloatAway, M as Chase, O as phaseOf, S as goToScene, T as FollowCamera, _ 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, j as Collector, k as DamageOnContact, 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, x as GameFlow, y as screenFlash } from "./gameplay-
|
|
1
|
+
import { A as Health, C as restartScene, D as DayNight, E as FloatAway, M as Chase, O as phaseOf, S as goToScene, T as FollowCamera, _ 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, j as Collector, k as DamageOnContact, 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, x as GameFlow, y as screenFlash } from "./gameplay-Dtzd2itW.js";
|
|
2
2
|
export { CameraShake, Chase, Collector, Cooldown, DamageOnContact, DayNight, FloatAway, 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 };
|