cubeforge 0.7.0 → 0.8.2
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/index.d.ts +87 -2
- package/dist/index.js +1066 -285
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -83,6 +83,20 @@ function applyDeltaSnapshot(baseline, delta) {
|
|
|
83
83
|
}
|
|
84
84
|
return { nextId: delta.nextId, rngState: delta.rngState, entities };
|
|
85
85
|
}
|
|
86
|
+
function _componentsChanged(a, b) {
|
|
87
|
+
if (a.length !== b.length) return true;
|
|
88
|
+
for (let i = 0; i < a.length; i++) {
|
|
89
|
+
const ca = a[i];
|
|
90
|
+
const cb = b[i];
|
|
91
|
+
if (ca["type"] !== cb["type"]) return true;
|
|
92
|
+
const keysA = Object.keys(ca);
|
|
93
|
+
if (keysA.length !== Object.keys(cb).length) return true;
|
|
94
|
+
for (const k of keysA) {
|
|
95
|
+
if (ca[k] !== cb[k]) return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
86
100
|
var ECSWorld = class {
|
|
87
101
|
nextId = 0;
|
|
88
102
|
// Secondary index: O(1) single-entity component lookup
|
|
@@ -201,6 +215,23 @@ var ECSWorld = class {
|
|
|
201
215
|
hasComponent(id, type) {
|
|
202
216
|
return this.componentIndex.get(id)?.has(type) ?? false;
|
|
203
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* Returns live references to all components on an entity.
|
|
220
|
+
* Useful for editor / inspector tooling. Returns an empty array if the
|
|
221
|
+
* entity does not exist.
|
|
222
|
+
*
|
|
223
|
+
* **Do not mutate structural fields** (e.g. `type`) — doing so will
|
|
224
|
+
* desync the archetype index. Mutating value fields (x, y, color …) is safe.
|
|
225
|
+
*/
|
|
226
|
+
getEntityComponents(id) {
|
|
227
|
+
const map = this.componentIndex.get(id);
|
|
228
|
+
if (!map) return [];
|
|
229
|
+
return [...map.values()];
|
|
230
|
+
}
|
|
231
|
+
/** Returns all live entity IDs currently in the world. */
|
|
232
|
+
getAllEntityIds() {
|
|
233
|
+
return [...this.componentIndex.keys()];
|
|
234
|
+
}
|
|
204
235
|
// Flush pending dirty flags into the query cache immediately.
|
|
205
236
|
// Called inline at the top of query() so any mid-frame mutation
|
|
206
237
|
// (destroyEntity, addComponent, removeComponent) is reflected before
|
|
@@ -437,7 +468,7 @@ var ECSWorld = class {
|
|
|
437
468
|
const removed = [];
|
|
438
469
|
for (const entity of current.entities) {
|
|
439
470
|
const base = baseMap.get(entity.id);
|
|
440
|
-
if (!base ||
|
|
471
|
+
if (!base || _componentsChanged(entity.components, base.components)) {
|
|
441
472
|
changed.push(entity);
|
|
442
473
|
}
|
|
443
474
|
}
|
|
@@ -2932,6 +2963,7 @@ function getSamplingKey(sampling) {
|
|
|
2932
2963
|
return `${sampling.min}|${sampling.mag}`;
|
|
2933
2964
|
}
|
|
2934
2965
|
function getTextureKey(sprite) {
|
|
2966
|
+
if (sprite.dynamicSrc) return sprite.dynamicSrc;
|
|
2935
2967
|
const src = sprite.image?.src || sprite.src;
|
|
2936
2968
|
const samplingKey = getSamplingKey(sprite.sampling);
|
|
2937
2969
|
const suffix = samplingKey ? `:s=${samplingKey}` : "";
|
|
@@ -3128,6 +3160,15 @@ var RenderSystem = class {
|
|
|
3128
3160
|
// FPS tracking
|
|
3129
3161
|
frameTimes = [];
|
|
3130
3162
|
lastTimestamp = 0;
|
|
3163
|
+
// ── Dynamic canvas textures (texSubImage2D optimization) ─────────────────
|
|
3164
|
+
_dynamicCanvases = /* @__PURE__ */ new Map();
|
|
3165
|
+
// ── Idle frame skip ──────────────────────────────────────────────────────
|
|
3166
|
+
_idleSkip = false;
|
|
3167
|
+
_prevSceneHash = -1;
|
|
3168
|
+
_idleFBO = null;
|
|
3169
|
+
_idleTex = null;
|
|
3170
|
+
_idleFBOW = 0;
|
|
3171
|
+
_idleFBOH = 0;
|
|
3131
3172
|
// ── Post-process ─────────────────────────────────────────────────────────
|
|
3132
3173
|
_ppOptions = {};
|
|
3133
3174
|
// Lazily created programs (null until first PP use)
|
|
@@ -3179,6 +3220,55 @@ var RenderSystem = class {
|
|
|
3179
3220
|
setPostProcessOptions(opts) {
|
|
3180
3221
|
this._ppOptions = opts;
|
|
3181
3222
|
}
|
|
3223
|
+
/**
|
|
3224
|
+
* Enable idle frame skip. When enabled the renderer computes a hash of all
|
|
3225
|
+
* visible entity positions, frame indices, and camera state each frame. If
|
|
3226
|
+
* the hash matches the previous frame the GPU draw calls are skipped entirely
|
|
3227
|
+
* and the cached scene is blitted to screen instead.
|
|
3228
|
+
*
|
|
3229
|
+
* Best for scenes that are frequently static (pause menus, cutscenes, HUDs).
|
|
3230
|
+
* Animations and active particles automatically disable the skip for that frame.
|
|
3231
|
+
*/
|
|
3232
|
+
setIdleFrameSkip(enabled) {
|
|
3233
|
+
this._idleSkip = enabled;
|
|
3234
|
+
}
|
|
3235
|
+
/**
|
|
3236
|
+
* Register an HTMLCanvasElement as a GPU texture that the renderer can sample.
|
|
3237
|
+
* The canvas is uploaded once on registration. Call {@link markDynamicCanvasDirty}
|
|
3238
|
+
* to schedule a re-upload before the next frame.
|
|
3239
|
+
*
|
|
3240
|
+
* Use the returned `id` as the `dynamicSrc` on a `<Sprite>` component.
|
|
3241
|
+
*/
|
|
3242
|
+
registerDynamicCanvas(id, canvas) {
|
|
3243
|
+
const { gl } = this;
|
|
3244
|
+
const tex = gl.createTexture();
|
|
3245
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
3246
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
|
|
3247
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
3248
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
3249
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
3250
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
3251
|
+
this._dynamicCanvases.set(id, { canvas, tex, dirty: false });
|
|
3252
|
+
this.textures.set(id, tex);
|
|
3253
|
+
this.touchTexture(id);
|
|
3254
|
+
}
|
|
3255
|
+
/**
|
|
3256
|
+
* Mark a dynamic canvas as modified so it will be re-uploaded to the GPU
|
|
3257
|
+
* (via `texSubImage2D`) at the start of the next rendered frame.
|
|
3258
|
+
* Only call this after actually drawing new content to the canvas.
|
|
3259
|
+
*/
|
|
3260
|
+
markDynamicCanvasDirty(id) {
|
|
3261
|
+
const entry = this._dynamicCanvases.get(id);
|
|
3262
|
+
if (entry) entry.dirty = true;
|
|
3263
|
+
}
|
|
3264
|
+
/** Remove a registered dynamic canvas and free its GPU texture. */
|
|
3265
|
+
unregisterDynamicCanvas(id) {
|
|
3266
|
+
const entry = this._dynamicCanvases.get(id);
|
|
3267
|
+
if (!entry) return;
|
|
3268
|
+
this.gl.deleteTexture(entry.tex);
|
|
3269
|
+
this._dynamicCanvases.delete(id);
|
|
3270
|
+
this.textures.delete(id);
|
|
3271
|
+
}
|
|
3182
3272
|
get _anyPPEnabled() {
|
|
3183
3273
|
const o = this._ppOptions;
|
|
3184
3274
|
return (o.bloom?.enabled ?? false) || (o.vignette?.enabled ?? false) || (o.chromaticAberration?.enabled ?? false) || (o.scanlines?.enabled ?? false);
|
|
@@ -3501,6 +3591,71 @@ var RenderSystem = class {
|
|
|
3501
3591
|
break;
|
|
3502
3592
|
}
|
|
3503
3593
|
}
|
|
3594
|
+
// ── Scene hash for idle frame skip ───────────────────────────────────────
|
|
3595
|
+
_computeSceneHash(world, camX, camY, zoom, shakeX, shakeY) {
|
|
3596
|
+
let h = 2166136261;
|
|
3597
|
+
const mix = (n) => {
|
|
3598
|
+
const i = n | 0;
|
|
3599
|
+
h = Math.imul(h ^ i & 255, 16777619);
|
|
3600
|
+
h = Math.imul(h ^ i >> 8 & 255, 16777619);
|
|
3601
|
+
h = Math.imul(h ^ i >> 16 & 255, 16777619);
|
|
3602
|
+
h = Math.imul(h ^ i >> 24 & 255, 16777619);
|
|
3603
|
+
};
|
|
3604
|
+
mix(camX * 100);
|
|
3605
|
+
mix(camY * 100);
|
|
3606
|
+
mix(zoom * 1e3);
|
|
3607
|
+
mix(shakeX * 1e3);
|
|
3608
|
+
mix(shakeY * 1e3);
|
|
3609
|
+
for (const id of world.query("Transform", "Sprite")) {
|
|
3610
|
+
const t = world.getComponent(id, "Transform");
|
|
3611
|
+
const s2 = world.getComponent(id, "Sprite");
|
|
3612
|
+
mix(id);
|
|
3613
|
+
mix(t.x * 100);
|
|
3614
|
+
mix(t.y * 100);
|
|
3615
|
+
mix(t.rotation * 1e3);
|
|
3616
|
+
mix(t.scaleX * 1e3);
|
|
3617
|
+
mix(t.scaleY * 1e3);
|
|
3618
|
+
mix(s2.frameIndex);
|
|
3619
|
+
mix(s2.visible ? 1 : 0);
|
|
3620
|
+
mix((s2.opacity ?? 1) * 255);
|
|
3621
|
+
}
|
|
3622
|
+
for (const id of world.query("AnimationState")) {
|
|
3623
|
+
const anim = world.getComponent(id, "AnimationState");
|
|
3624
|
+
if (anim.playing) return -1;
|
|
3625
|
+
}
|
|
3626
|
+
for (const id of world.query("ParticlePool")) {
|
|
3627
|
+
const pool = world.getComponent(id, "ParticlePool");
|
|
3628
|
+
if (pool.active || pool.particles.length > 0) return -1;
|
|
3629
|
+
}
|
|
3630
|
+
for (const id of world.query("SquashStretch")) {
|
|
3631
|
+
const ss = world.getComponent(id, "SquashStretch");
|
|
3632
|
+
mix(ss.currentScaleX * 1e3);
|
|
3633
|
+
mix(ss.currentScaleY * 1e3);
|
|
3634
|
+
}
|
|
3635
|
+
return h;
|
|
3636
|
+
}
|
|
3637
|
+
_ensureIdleFBO(w, h) {
|
|
3638
|
+
if (this._idleFBOW === w && this._idleFBOH === h && this._idleFBO) return;
|
|
3639
|
+
const { gl } = this;
|
|
3640
|
+
if (this._idleFBO) gl.deleteFramebuffer(this._idleFBO);
|
|
3641
|
+
if (this._idleTex) gl.deleteTexture(this._idleTex);
|
|
3642
|
+
const tex = gl.createTexture();
|
|
3643
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
3644
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
|
3645
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
3646
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
3647
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
3648
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
3649
|
+
const fbo = gl.createFramebuffer();
|
|
3650
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
|
3651
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
|
|
3652
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
3653
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
3654
|
+
this._idleFBO = fbo;
|
|
3655
|
+
this._idleTex = tex;
|
|
3656
|
+
this._idleFBOW = w;
|
|
3657
|
+
this._idleFBOH = h;
|
|
3658
|
+
}
|
|
3504
3659
|
// ── Instanced draw call ────────────────────────────────────────────────────
|
|
3505
3660
|
flush(count, textureKey, sampling, blendMode, shapeSpriteRef) {
|
|
3506
3661
|
if (count === 0) return;
|
|
@@ -3721,6 +3876,24 @@ var RenderSystem = class {
|
|
|
3721
3876
|
ss.currentScaleX += (tScX - ss.currentScaleX) * ss.recovery * dt;
|
|
3722
3877
|
ss.currentScaleY += (tScY - ss.currentScaleY) * ss.recovery * dt;
|
|
3723
3878
|
}
|
|
3879
|
+
for (const entry of this._dynamicCanvases.values()) {
|
|
3880
|
+
if (!entry.dirty) continue;
|
|
3881
|
+
gl.bindTexture(gl.TEXTURE_2D, entry.tex);
|
|
3882
|
+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, entry.canvas);
|
|
3883
|
+
entry.dirty = false;
|
|
3884
|
+
}
|
|
3885
|
+
if (this._idleSkip) {
|
|
3886
|
+
this._ensureIdleFBO(W, H);
|
|
3887
|
+
const hash = this._computeSceneHash(world, camX, camY, zoom, shakeX, shakeY);
|
|
3888
|
+
if (hash !== -1 && hash === this._prevSceneHash) {
|
|
3889
|
+
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this._idleFBO);
|
|
3890
|
+
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
|
|
3891
|
+
gl.blitFramebuffer(0, 0, W, H, 0, 0, W, H, gl.COLOR_BUFFER_BIT, gl.NEAREST);
|
|
3892
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
3893
|
+
return;
|
|
3894
|
+
}
|
|
3895
|
+
this._prevSceneHash = hash;
|
|
3896
|
+
}
|
|
3724
3897
|
const ppEnabled = this._anyPPEnabled;
|
|
3725
3898
|
if (ppEnabled) {
|
|
3726
3899
|
this._ensurePPPrograms();
|
|
@@ -3866,7 +4039,7 @@ var RenderSystem = class {
|
|
|
3866
4039
|
const ss = world.getComponent(id, "SquashStretch");
|
|
3867
4040
|
const scaleXMod = ss ? ss.currentScaleX : 1;
|
|
3868
4041
|
const scaleYMod = ss ? ss.currentScaleY : 1;
|
|
3869
|
-
const hasTexture = sprite.image && sprite.image.complete && sprite.image.naturalWidth > 0;
|
|
4042
|
+
const hasTexture = sprite.image && sprite.image.complete && sprite.image.naturalWidth > 0 || sprite.dynamicSrc !== void 0 && this._dynamicCanvases.has(sprite.dynamicSrc);
|
|
3870
4043
|
const opacity = sprite.opacity ?? 1;
|
|
3871
4044
|
let [r, g, b, a] = hasTexture ? [1, 1, 1, 1] : parseCSSColor(sprite.color);
|
|
3872
4045
|
a *= opacity;
|
|
@@ -4337,6 +4510,12 @@ var RenderSystem = class {
|
|
|
4337
4510
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
4338
4511
|
this._applyPostProcess(W, H);
|
|
4339
4512
|
}
|
|
4513
|
+
if (this._idleSkip && this._idleFBO) {
|
|
4514
|
+
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
|
|
4515
|
+
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this._idleFBO);
|
|
4516
|
+
gl.blitFramebuffer(0, 0, W, H, 0, 0, W, H, gl.COLOR_BUFFER_BIT, gl.NEAREST);
|
|
4517
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
4518
|
+
}
|
|
4340
4519
|
const now = performance.now();
|
|
4341
4520
|
if (this.lastTimestamp > 0) {
|
|
4342
4521
|
this.frameTimes.push(now - this.lastTimestamp);
|
|
@@ -7206,6 +7385,7 @@ function Sprite({
|
|
|
7206
7385
|
height,
|
|
7207
7386
|
color = "#ffffff",
|
|
7208
7387
|
src,
|
|
7388
|
+
dynamicSrc,
|
|
7209
7389
|
offsetX = 0,
|
|
7210
7390
|
offsetY = 0,
|
|
7211
7391
|
zIndex = 0,
|
|
@@ -7257,6 +7437,7 @@ function Sprite({
|
|
|
7257
7437
|
height,
|
|
7258
7438
|
color,
|
|
7259
7439
|
src,
|
|
7440
|
+
dynamicSrc,
|
|
7260
7441
|
offsetX,
|
|
7261
7442
|
offsetY,
|
|
7262
7443
|
zIndex,
|
|
@@ -7338,6 +7519,7 @@ function Sprite({
|
|
|
7338
7519
|
const comp = engine.ecs.getComponent(entityId, "Sprite");
|
|
7339
7520
|
if (!comp) return;
|
|
7340
7521
|
comp.color = color;
|
|
7522
|
+
comp.dynamicSrc = dynamicSrc;
|
|
7341
7523
|
comp.visible = visible;
|
|
7342
7524
|
comp.flipX = flipX;
|
|
7343
7525
|
comp.flipY = flipY;
|
|
@@ -7357,6 +7539,7 @@ function Sprite({
|
|
|
7357
7539
|
comp.starInnerRadius = starInnerRadius;
|
|
7358
7540
|
}, [
|
|
7359
7541
|
color,
|
|
7542
|
+
dynamicSrc,
|
|
7360
7543
|
visible,
|
|
7361
7544
|
flipX,
|
|
7362
7545
|
flipY,
|
|
@@ -8597,7 +8780,6 @@ function Checkpoint({
|
|
|
8597
8780
|
// src/components/Tilemap.tsx
|
|
8598
8781
|
import { useEffect as useEffect30, useState as useState6, useContext as useContext20 } from "react";
|
|
8599
8782
|
import { Fragment as Fragment5, jsx as jsx10 } from "react/jsx-runtime";
|
|
8600
|
-
var animatedTiles = /* @__PURE__ */ new Map();
|
|
8601
8783
|
function getProperty(props, name) {
|
|
8602
8784
|
return props?.find((p) => p.name === name)?.value;
|
|
8603
8785
|
}
|
|
@@ -8629,6 +8811,7 @@ function Tilemap({
|
|
|
8629
8811
|
useEffect30(() => {
|
|
8630
8812
|
if (!engine) return;
|
|
8631
8813
|
const createdEntities = [];
|
|
8814
|
+
const animatedTiles = /* @__PURE__ */ new Map();
|
|
8632
8815
|
async function load() {
|
|
8633
8816
|
let mapData;
|
|
8634
8817
|
try {
|
|
@@ -8764,6 +8947,7 @@ function Tilemap({
|
|
|
8764
8947
|
if (frame) {
|
|
8765
8948
|
sprite.frame = { sx: frame.sx, sy: frame.sy, sw: frame.sw, sh: frame.sh };
|
|
8766
8949
|
engine.assets.loadImage(frame.imageSrc).then((img) => {
|
|
8950
|
+
if (!engine.ecs.hasEntity(eid)) return;
|
|
8767
8951
|
const s2 = engine.ecs.getComponent(eid, "Sprite");
|
|
8768
8952
|
if (s2) s2.image = img;
|
|
8769
8953
|
}).catch(() => {
|
|
@@ -8779,6 +8963,7 @@ function Tilemap({
|
|
|
8779
8963
|
animatedTiles.set(eid, state);
|
|
8780
8964
|
const firstFrameRegion = getFrameForLocalId(resolved.tileset, frames[0]);
|
|
8781
8965
|
engine.assets.loadImage(firstFrameRegion.imageSrc).then((img) => {
|
|
8966
|
+
if (!engine.ecs.hasEntity(eid)) return;
|
|
8782
8967
|
const s2 = engine.ecs.getComponent(eid, "Sprite");
|
|
8783
8968
|
if (s2) {
|
|
8784
8969
|
s2.image = img;
|
|
@@ -10256,11 +10441,51 @@ function useWebGLPostProcess(opts) {
|
|
|
10256
10441
|
}, [engine, optsKey]);
|
|
10257
10442
|
}
|
|
10258
10443
|
|
|
10444
|
+
// src/hooks/useDynamicCanvas.ts
|
|
10445
|
+
import { useCallback as useCallback7, useEffect as useEffect59, useMemo as useMemo10, useRef as useRef23 } from "react";
|
|
10446
|
+
function useDynamicCanvas(width, height) {
|
|
10447
|
+
const engine = useGame();
|
|
10448
|
+
const idRef = useRef23(`__dynamic__:${Math.random().toString(36).slice(2)}`);
|
|
10449
|
+
const id = idRef.current;
|
|
10450
|
+
const canvas = useMemo10(() => {
|
|
10451
|
+
const c = document.createElement("canvas");
|
|
10452
|
+
c.width = width;
|
|
10453
|
+
c.height = height;
|
|
10454
|
+
return c;
|
|
10455
|
+
}, [width, height]);
|
|
10456
|
+
const ctx = useMemo10(() => canvas.getContext("2d"), [canvas]);
|
|
10457
|
+
useEffect59(() => {
|
|
10458
|
+
const rs = engine.activeRenderSystem;
|
|
10459
|
+
rs.registerDynamicCanvas?.(id, canvas);
|
|
10460
|
+
return () => {
|
|
10461
|
+
rs.unregisterDynamicCanvas?.(id);
|
|
10462
|
+
};
|
|
10463
|
+
}, [engine, id, canvas]);
|
|
10464
|
+
const markDirty = useCallback7(() => {
|
|
10465
|
+
const rs = engine.activeRenderSystem;
|
|
10466
|
+
rs.markDynamicCanvasDirty?.(id);
|
|
10467
|
+
}, [engine, id]);
|
|
10468
|
+
return useMemo10(() => ({ id, canvas, ctx, markDirty }), [id, canvas, ctx, markDirty]);
|
|
10469
|
+
}
|
|
10470
|
+
|
|
10471
|
+
// src/hooks/useIdleFrameSkip.ts
|
|
10472
|
+
import { useEffect as useEffect60 } from "react";
|
|
10473
|
+
function useIdleFrameSkip(enabled = true) {
|
|
10474
|
+
const engine = useGame();
|
|
10475
|
+
useEffect60(() => {
|
|
10476
|
+
const rs = engine.activeRenderSystem;
|
|
10477
|
+
rs.setIdleFrameSkip?.(enabled);
|
|
10478
|
+
return () => {
|
|
10479
|
+
rs.setIdleFrameSkip?.(false);
|
|
10480
|
+
};
|
|
10481
|
+
}, [engine, enabled]);
|
|
10482
|
+
}
|
|
10483
|
+
|
|
10259
10484
|
// src/hooks/useAudioListener.ts
|
|
10260
|
-
import { useEffect as
|
|
10485
|
+
import { useEffect as useEffect61, useContext as useContext49 } from "react";
|
|
10261
10486
|
function useAudioListener() {
|
|
10262
10487
|
const engine = useContext49(EngineContext);
|
|
10263
|
-
|
|
10488
|
+
useEffect61(() => {
|
|
10264
10489
|
const eid = engine.ecs.createEntity();
|
|
10265
10490
|
engine.ecs.addComponent(
|
|
10266
10491
|
eid,
|
|
@@ -10304,13 +10529,13 @@ function useTouch() {
|
|
|
10304
10529
|
}
|
|
10305
10530
|
|
|
10306
10531
|
// src/hooks/useGestures.ts
|
|
10307
|
-
import { useEffect as
|
|
10532
|
+
import { useEffect as useEffect62, useRef as useRef24 } from "react";
|
|
10308
10533
|
function useGestures(handlers, opts = {}) {
|
|
10309
|
-
const handlersRef =
|
|
10534
|
+
const handlersRef = useRef24(handlers);
|
|
10310
10535
|
handlersRef.current = handlers;
|
|
10311
|
-
const optsRef =
|
|
10536
|
+
const optsRef = useRef24(opts);
|
|
10312
10537
|
optsRef.current = opts;
|
|
10313
|
-
|
|
10538
|
+
useEffect62(() => {
|
|
10314
10539
|
const target = optsRef.current.target ?? window;
|
|
10315
10540
|
let starts = [];
|
|
10316
10541
|
let longPressTimer = null;
|
|
@@ -10470,14 +10695,14 @@ var touchHapticsControls = {
|
|
|
10470
10695
|
};
|
|
10471
10696
|
|
|
10472
10697
|
// src/hooks/useTimer.ts
|
|
10473
|
-
import { useRef as
|
|
10698
|
+
import { useRef as useRef25, useCallback as useCallback8, useEffect as useEffect63, useContext as useContext51 } from "react";
|
|
10474
10699
|
function useTimer(duration, onComplete, opts) {
|
|
10475
10700
|
const engine = useContext51(EngineContext);
|
|
10476
|
-
const onCompleteRef =
|
|
10701
|
+
const onCompleteRef = useRef25(onComplete);
|
|
10477
10702
|
onCompleteRef.current = onComplete;
|
|
10478
|
-
const loopRef =
|
|
10703
|
+
const loopRef = useRef25(opts?.loop ?? false);
|
|
10479
10704
|
loopRef.current = opts?.loop ?? false;
|
|
10480
|
-
const timerRef =
|
|
10705
|
+
const timerRef = useRef25(null);
|
|
10481
10706
|
if (!timerRef.current) {
|
|
10482
10707
|
timerRef.current = createTimer(
|
|
10483
10708
|
duration,
|
|
@@ -10490,7 +10715,7 @@ function useTimer(duration, onComplete, opts) {
|
|
|
10490
10715
|
opts?.autoStart ?? false
|
|
10491
10716
|
);
|
|
10492
10717
|
}
|
|
10493
|
-
|
|
10718
|
+
useEffect63(() => {
|
|
10494
10719
|
const eid = engine.ecs.createEntity();
|
|
10495
10720
|
engine.ecs.addComponent(
|
|
10496
10721
|
eid,
|
|
@@ -10502,13 +10727,13 @@ function useTimer(duration, onComplete, opts) {
|
|
|
10502
10727
|
if (engine.ecs.hasEntity(eid)) engine.ecs.destroyEntity(eid);
|
|
10503
10728
|
};
|
|
10504
10729
|
}, [engine.ecs]);
|
|
10505
|
-
const start2 =
|
|
10730
|
+
const start2 = useCallback8(() => {
|
|
10506
10731
|
timerRef.current.start();
|
|
10507
10732
|
}, []);
|
|
10508
|
-
const stop =
|
|
10733
|
+
const stop = useCallback8(() => {
|
|
10509
10734
|
timerRef.current.stop();
|
|
10510
10735
|
}, []);
|
|
10511
|
-
const reset =
|
|
10736
|
+
const reset = useCallback8(() => {
|
|
10512
10737
|
timerRef.current.reset();
|
|
10513
10738
|
}, []);
|
|
10514
10739
|
return {
|
|
@@ -10531,15 +10756,15 @@ function useTimer(duration, onComplete, opts) {
|
|
|
10531
10756
|
}
|
|
10532
10757
|
|
|
10533
10758
|
// src/hooks/useCoroutine.ts
|
|
10534
|
-
import { useRef as
|
|
10759
|
+
import { useRef as useRef26, useEffect as useEffect64, useContext as useContext52 } from "react";
|
|
10535
10760
|
var wait = (seconds) => ({ type: "wait", seconds });
|
|
10536
10761
|
var waitFrames = (frames) => ({ type: "waitFrames", frames });
|
|
10537
10762
|
var waitUntil = (condition) => ({ type: "waitUntil", condition });
|
|
10538
10763
|
var nextCoroutineId = 1;
|
|
10539
10764
|
function useCoroutine() {
|
|
10540
10765
|
const engine = useContext52(EngineContext);
|
|
10541
|
-
const coroutinesRef =
|
|
10542
|
-
|
|
10766
|
+
const coroutinesRef = useRef26(/* @__PURE__ */ new Map());
|
|
10767
|
+
useEffect64(() => {
|
|
10543
10768
|
const eid = engine.ecs.createEntity();
|
|
10544
10769
|
engine.ecs.addComponent(
|
|
10545
10770
|
eid,
|
|
@@ -10604,33 +10829,33 @@ function useCoroutine() {
|
|
|
10604
10829
|
return coroutinesRef.current.size;
|
|
10605
10830
|
}
|
|
10606
10831
|
};
|
|
10607
|
-
const controlsRef =
|
|
10832
|
+
const controlsRef = useRef26(controls);
|
|
10608
10833
|
return controlsRef.current;
|
|
10609
10834
|
}
|
|
10610
10835
|
|
|
10611
10836
|
// src/hooks/useSceneManager.ts
|
|
10612
|
-
import { useState as useState13, useCallback as
|
|
10837
|
+
import { useState as useState13, useCallback as useCallback9, useRef as useRef27 } from "react";
|
|
10613
10838
|
function useSceneManager(initialScene) {
|
|
10614
10839
|
const [stack, setStack] = useState13([initialScene]);
|
|
10615
|
-
const stackRef =
|
|
10840
|
+
const stackRef = useRef27(stack);
|
|
10616
10841
|
stackRef.current = stack;
|
|
10617
|
-
const push =
|
|
10842
|
+
const push = useCallback9((scene) => {
|
|
10618
10843
|
setStack((prev) => [...prev, scene]);
|
|
10619
10844
|
}, []);
|
|
10620
|
-
const pop =
|
|
10845
|
+
const pop = useCallback9(() => {
|
|
10621
10846
|
const prev = stackRef.current;
|
|
10622
10847
|
if (prev.length <= 1) return void 0;
|
|
10623
10848
|
const popped = prev[prev.length - 1];
|
|
10624
10849
|
setStack(prev.slice(0, -1));
|
|
10625
10850
|
return popped;
|
|
10626
10851
|
}, []);
|
|
10627
|
-
const replace =
|
|
10852
|
+
const replace = useCallback9((scene) => {
|
|
10628
10853
|
setStack((prev) => [...prev.slice(0, -1), scene]);
|
|
10629
10854
|
}, []);
|
|
10630
|
-
const reset =
|
|
10855
|
+
const reset = useCallback9((scene) => {
|
|
10631
10856
|
setStack([scene]);
|
|
10632
10857
|
}, []);
|
|
10633
|
-
const has =
|
|
10858
|
+
const has = useCallback9(
|
|
10634
10859
|
(scene) => {
|
|
10635
10860
|
return stack.includes(scene);
|
|
10636
10861
|
},
|
|
@@ -10648,7 +10873,7 @@ function useSceneManager(initialScene) {
|
|
|
10648
10873
|
}
|
|
10649
10874
|
|
|
10650
10875
|
// src/hooks/useSceneTransition.ts
|
|
10651
|
-
import { useState as useState14, useCallback as
|
|
10876
|
+
import { useState as useState14, useCallback as useCallback10, useRef as useRef28, useEffect as useEffect65 } from "react";
|
|
10652
10877
|
function useSceneTransition(initialScene, defaultTransition) {
|
|
10653
10878
|
const [stack, setStack] = useState14([initialScene]);
|
|
10654
10879
|
const [transState, setTransState] = useState14({
|
|
@@ -10657,11 +10882,11 @@ function useSceneTransition(initialScene, defaultTransition) {
|
|
|
10657
10882
|
effect: null,
|
|
10658
10883
|
pendingAction: null
|
|
10659
10884
|
});
|
|
10660
|
-
const stackRef =
|
|
10885
|
+
const stackRef = useRef28(stack);
|
|
10661
10886
|
stackRef.current = stack;
|
|
10662
|
-
const transRef =
|
|
10887
|
+
const transRef = useRef28(transState);
|
|
10663
10888
|
transRef.current = transState;
|
|
10664
|
-
|
|
10889
|
+
useEffect65(() => {
|
|
10665
10890
|
if (transState.phase === "idle") return;
|
|
10666
10891
|
const effect = transState.effect;
|
|
10667
10892
|
if (!effect || effect.type === "instant") return;
|
|
@@ -10690,7 +10915,7 @@ function useSceneTransition(initialScene, defaultTransition) {
|
|
|
10690
10915
|
rafId2 = requestAnimationFrame(animate);
|
|
10691
10916
|
return () => cancelAnimationFrame(rafId2);
|
|
10692
10917
|
}, [transState.phase, transState.effect]);
|
|
10693
|
-
const startTransition =
|
|
10918
|
+
const startTransition = useCallback10(
|
|
10694
10919
|
(effect, action) => {
|
|
10695
10920
|
const eff = effect ?? defaultTransition ?? { type: "instant" };
|
|
10696
10921
|
if (eff.type === "instant" || isReducedMotionPreferred()) {
|
|
@@ -10706,13 +10931,13 @@ function useSceneTransition(initialScene, defaultTransition) {
|
|
|
10706
10931
|
},
|
|
10707
10932
|
[defaultTransition]
|
|
10708
10933
|
);
|
|
10709
|
-
const push =
|
|
10934
|
+
const push = useCallback10(
|
|
10710
10935
|
(scene, transition) => {
|
|
10711
10936
|
startTransition(transition, () => setStack((prev) => [...prev, scene]));
|
|
10712
10937
|
},
|
|
10713
10938
|
[startTransition]
|
|
10714
10939
|
);
|
|
10715
|
-
const pop =
|
|
10940
|
+
const pop = useCallback10(
|
|
10716
10941
|
(transition) => {
|
|
10717
10942
|
const prev = stackRef.current;
|
|
10718
10943
|
if (prev.length <= 1) return void 0;
|
|
@@ -10722,13 +10947,13 @@ function useSceneTransition(initialScene, defaultTransition) {
|
|
|
10722
10947
|
},
|
|
10723
10948
|
[startTransition]
|
|
10724
10949
|
);
|
|
10725
|
-
const replace =
|
|
10950
|
+
const replace = useCallback10(
|
|
10726
10951
|
(scene, transition) => {
|
|
10727
10952
|
startTransition(transition, () => setStack((prev) => [...prev.slice(0, -1), scene]));
|
|
10728
10953
|
},
|
|
10729
10954
|
[startTransition]
|
|
10730
10955
|
);
|
|
10731
|
-
const reset =
|
|
10956
|
+
const reset = useCallback10(
|
|
10732
10957
|
(scene, transition) => {
|
|
10733
10958
|
startTransition(transition, () => setStack([scene]));
|
|
10734
10959
|
},
|
|
@@ -10829,10 +11054,10 @@ function SceneTransitionOverlay({ controls }) {
|
|
|
10829
11054
|
}
|
|
10830
11055
|
|
|
10831
11056
|
// src/hooks/useHitstop.ts
|
|
10832
|
-
import { useContext as useContext53, useCallback as
|
|
11057
|
+
import { useContext as useContext53, useCallback as useCallback11 } from "react";
|
|
10833
11058
|
function useHitstop() {
|
|
10834
11059
|
const engine = useContext53(EngineContext);
|
|
10835
|
-
const freeze =
|
|
11060
|
+
const freeze = useCallback11(
|
|
10836
11061
|
(seconds) => {
|
|
10837
11062
|
engine.loop.hitPause(seconds);
|
|
10838
11063
|
},
|
|
@@ -10842,16 +11067,16 @@ function useHitstop() {
|
|
|
10842
11067
|
}
|
|
10843
11068
|
|
|
10844
11069
|
// src/hooks/useInputBuffer.ts
|
|
10845
|
-
import { useMemo as
|
|
11070
|
+
import { useMemo as useMemo11 } from "react";
|
|
10846
11071
|
function useInputBuffer(opts) {
|
|
10847
|
-
return
|
|
11072
|
+
return useMemo11(() => new InputBuffer(opts), []);
|
|
10848
11073
|
}
|
|
10849
11074
|
|
|
10850
11075
|
// src/hooks/useComboDetector.ts
|
|
10851
|
-
import { useMemo as
|
|
11076
|
+
import { useMemo as useMemo12, useRef as useRef29 } from "react";
|
|
10852
11077
|
function useComboDetector(combos) {
|
|
10853
|
-
const lastComboRef =
|
|
10854
|
-
const result =
|
|
11078
|
+
const lastComboRef = useRef29(null);
|
|
11079
|
+
const result = useMemo12(() => {
|
|
10855
11080
|
const detector = new ComboDetector({ combos });
|
|
10856
11081
|
const api = {
|
|
10857
11082
|
feed(action) {
|
|
@@ -10873,11 +11098,11 @@ function useComboDetector(combos) {
|
|
|
10873
11098
|
}
|
|
10874
11099
|
|
|
10875
11100
|
// src/hooks/useParent.ts
|
|
10876
|
-
import { useEffect as
|
|
11101
|
+
import { useEffect as useEffect66, useContext as useContext54 } from "react";
|
|
10877
11102
|
function useParent(childEntityId, parentEntityId) {
|
|
10878
11103
|
const engine = useContext54(EngineContext);
|
|
10879
11104
|
if (!engine) throw new Error("useParent must be used inside <Game>");
|
|
10880
|
-
|
|
11105
|
+
useEffect66(() => {
|
|
10881
11106
|
setParent(engine.ecs, childEntityId, parentEntityId);
|
|
10882
11107
|
return () => {
|
|
10883
11108
|
removeParent(engine.ecs, childEntityId);
|
|
@@ -10886,7 +11111,7 @@ function useParent(childEntityId, parentEntityId) {
|
|
|
10886
11111
|
}
|
|
10887
11112
|
|
|
10888
11113
|
// src/hooks/useAccessibility.ts
|
|
10889
|
-
import { useCallback as
|
|
11114
|
+
import { useCallback as useCallback12, useSyncExternalStore } from "react";
|
|
10890
11115
|
var _version = 0;
|
|
10891
11116
|
var _listeners = /* @__PURE__ */ new Set();
|
|
10892
11117
|
function subscribe(cb) {
|
|
@@ -10898,12 +11123,12 @@ function getSnapshot() {
|
|
|
10898
11123
|
}
|
|
10899
11124
|
function useAccessibility() {
|
|
10900
11125
|
useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
10901
|
-
const setOptions =
|
|
11126
|
+
const setOptions = useCallback12((opts) => {
|
|
10902
11127
|
setAccessibilityOptions(opts);
|
|
10903
11128
|
_version++;
|
|
10904
11129
|
for (const cb of _listeners) cb();
|
|
10905
11130
|
}, []);
|
|
10906
|
-
const announce =
|
|
11131
|
+
const announce = useCallback12((text, priority) => {
|
|
10907
11132
|
announceToScreenReader(text, priority);
|
|
10908
11133
|
}, []);
|
|
10909
11134
|
return {
|
|
@@ -10914,18 +11139,18 @@ function useAccessibility() {
|
|
|
10914
11139
|
}
|
|
10915
11140
|
|
|
10916
11141
|
// src/hooks/useHMR.ts
|
|
10917
|
-
import { useEffect as
|
|
11142
|
+
import { useEffect as useEffect67, useRef as useRef30, useMemo as useMemo13 } from "react";
|
|
10918
11143
|
var idCounter = 0;
|
|
10919
11144
|
function useHMR(hmrKey) {
|
|
10920
|
-
const idRef =
|
|
11145
|
+
const idRef = useRef30(null);
|
|
10921
11146
|
if (idRef.current === null) {
|
|
10922
11147
|
idRef.current = hmrKey ?? `__hmr_${idCounter++}`;
|
|
10923
11148
|
}
|
|
10924
11149
|
const key = idRef.current;
|
|
10925
11150
|
const isHotReload = hmrLoadState(key) !== void 0;
|
|
10926
|
-
const disposeRef =
|
|
10927
|
-
const acceptRef =
|
|
10928
|
-
|
|
11151
|
+
const disposeRef = useRef30(null);
|
|
11152
|
+
const acceptRef = useRef30(null);
|
|
11153
|
+
useEffect67(() => {
|
|
10929
11154
|
const hot = import.meta.hot;
|
|
10930
11155
|
if (!hot) return;
|
|
10931
11156
|
hot.dispose(() => {
|
|
@@ -10939,7 +11164,7 @@ function useHMR(hmrKey) {
|
|
|
10939
11164
|
acceptRef.current(prev);
|
|
10940
11165
|
}
|
|
10941
11166
|
}, [key]);
|
|
10942
|
-
return
|
|
11167
|
+
return useMemo13(
|
|
10943
11168
|
() => ({
|
|
10944
11169
|
onDispose(handler) {
|
|
10945
11170
|
disposeRef.current = handler;
|
|
@@ -10958,11 +11183,11 @@ function useHMR(hmrKey) {
|
|
|
10958
11183
|
}
|
|
10959
11184
|
|
|
10960
11185
|
// src/hooks/useSquashStretch.ts
|
|
10961
|
-
import { useCallback as
|
|
11186
|
+
import { useCallback as useCallback13, useContext as useContext55 } from "react";
|
|
10962
11187
|
function useSquashStretch() {
|
|
10963
11188
|
const engine = useContext55(EngineContext);
|
|
10964
11189
|
const entityId = useContext55(EntityContext);
|
|
10965
|
-
const trigger =
|
|
11190
|
+
const trigger = useCallback13(
|
|
10966
11191
|
(scaleX, scaleY) => {
|
|
10967
11192
|
const ss = engine.ecs.getComponent(entityId, "SquashStretch");
|
|
10968
11193
|
if (!ss) return;
|
|
@@ -10975,16 +11200,16 @@ function useSquashStretch() {
|
|
|
10975
11200
|
}
|
|
10976
11201
|
|
|
10977
11202
|
// src/hooks/useHistory.ts
|
|
10978
|
-
import { useCallback as
|
|
11203
|
+
import { useCallback as useCallback14, useContext as useContext56, useEffect as useEffect68, useRef as useRef31, useState as useState15 } from "react";
|
|
10979
11204
|
function useHistory(options) {
|
|
10980
11205
|
const engine = useContext56(EngineContext);
|
|
10981
11206
|
const capacity = options?.capacity ?? 50;
|
|
10982
11207
|
const bindKeys = options?.bindKeyboardShortcuts ?? false;
|
|
10983
|
-
const stackRef =
|
|
10984
|
-
const indexRef =
|
|
11208
|
+
const stackRef = useRef31([]);
|
|
11209
|
+
const indexRef = useRef31(-1);
|
|
10985
11210
|
const [version, setVersion] = useState15(0);
|
|
10986
|
-
const bump =
|
|
10987
|
-
const push =
|
|
11211
|
+
const bump = useCallback14(() => setVersion((v) => v + 1), []);
|
|
11212
|
+
const push = useCallback14(() => {
|
|
10988
11213
|
const snap = engine.ecs.getSnapshot();
|
|
10989
11214
|
const stack = stackRef.current;
|
|
10990
11215
|
if (indexRef.current < stack.length - 1) {
|
|
@@ -10995,14 +11220,14 @@ function useHistory(options) {
|
|
|
10995
11220
|
indexRef.current = stack.length - 1;
|
|
10996
11221
|
bump();
|
|
10997
11222
|
}, [engine, capacity, bump]);
|
|
10998
|
-
const undo =
|
|
11223
|
+
const undo = useCallback14(() => {
|
|
10999
11224
|
if (indexRef.current <= 0) return;
|
|
11000
11225
|
indexRef.current -= 1;
|
|
11001
11226
|
engine.ecs.restoreSnapshot(stackRef.current[indexRef.current]);
|
|
11002
11227
|
engine.loop.markDirty();
|
|
11003
11228
|
bump();
|
|
11004
11229
|
}, [engine, bump]);
|
|
11005
|
-
const redo =
|
|
11230
|
+
const redo = useCallback14(() => {
|
|
11006
11231
|
const stack = stackRef.current;
|
|
11007
11232
|
if (indexRef.current >= stack.length - 1) return;
|
|
11008
11233
|
indexRef.current += 1;
|
|
@@ -11010,12 +11235,12 @@ function useHistory(options) {
|
|
|
11010
11235
|
engine.loop.markDirty();
|
|
11011
11236
|
bump();
|
|
11012
11237
|
}, [engine, bump]);
|
|
11013
|
-
const clear =
|
|
11238
|
+
const clear = useCallback14(() => {
|
|
11014
11239
|
stackRef.current = [];
|
|
11015
11240
|
indexRef.current = -1;
|
|
11016
11241
|
bump();
|
|
11017
11242
|
}, [bump]);
|
|
11018
|
-
|
|
11243
|
+
useEffect68(() => {
|
|
11019
11244
|
if (!bindKeys) return;
|
|
11020
11245
|
const onKey = (e) => {
|
|
11021
11246
|
const mod = e.ctrlKey || e.metaKey;
|
|
@@ -11040,13 +11265,13 @@ function useHistory(options) {
|
|
|
11040
11265
|
}
|
|
11041
11266
|
|
|
11042
11267
|
// src/hooks/useSelection.tsx
|
|
11043
|
-
import { createContext as createContext2, useCallback as
|
|
11268
|
+
import { createContext as createContext2, useCallback as useCallback15, useContext as useContext57, useEffect as useEffect69, useMemo as useMemo14, useState as useState16 } from "react";
|
|
11044
11269
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
11045
11270
|
var SelectionContext = createContext2(null);
|
|
11046
11271
|
function Selection({ initial, onChange, children }) {
|
|
11047
11272
|
const engine = useContext57(EngineContext);
|
|
11048
11273
|
const [selected, setSelected] = useState16(initial ?? []);
|
|
11049
|
-
|
|
11274
|
+
useEffect69(() => {
|
|
11050
11275
|
if (!engine) return;
|
|
11051
11276
|
return engine.ecs.onDestroyEntity((destroyedId) => {
|
|
11052
11277
|
setSelected((prev) => {
|
|
@@ -11057,14 +11282,14 @@ function Selection({ initial, onChange, children }) {
|
|
|
11057
11282
|
});
|
|
11058
11283
|
});
|
|
11059
11284
|
}, [engine, onChange]);
|
|
11060
|
-
const commit =
|
|
11285
|
+
const commit = useCallback15(
|
|
11061
11286
|
(next) => {
|
|
11062
11287
|
setSelected(next);
|
|
11063
11288
|
onChange?.(next);
|
|
11064
11289
|
},
|
|
11065
11290
|
[onChange]
|
|
11066
11291
|
);
|
|
11067
|
-
const select =
|
|
11292
|
+
const select = useCallback15(
|
|
11068
11293
|
(id, opts) => {
|
|
11069
11294
|
if (opts?.additive) {
|
|
11070
11295
|
setSelected((prev) => {
|
|
@@ -11079,7 +11304,7 @@ function Selection({ initial, onChange, children }) {
|
|
|
11079
11304
|
},
|
|
11080
11305
|
[commit, onChange]
|
|
11081
11306
|
);
|
|
11082
|
-
const deselect =
|
|
11307
|
+
const deselect = useCallback15(
|
|
11083
11308
|
(id) => {
|
|
11084
11309
|
setSelected((prev) => {
|
|
11085
11310
|
if (!prev.includes(id)) return prev;
|
|
@@ -11090,7 +11315,7 @@ function Selection({ initial, onChange, children }) {
|
|
|
11090
11315
|
},
|
|
11091
11316
|
[onChange]
|
|
11092
11317
|
);
|
|
11093
|
-
const toggle =
|
|
11318
|
+
const toggle = useCallback15(
|
|
11094
11319
|
(id) => {
|
|
11095
11320
|
setSelected((prev) => {
|
|
11096
11321
|
const next = prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id];
|
|
@@ -11100,9 +11325,9 @@ function Selection({ initial, onChange, children }) {
|
|
|
11100
11325
|
},
|
|
11101
11326
|
[onChange]
|
|
11102
11327
|
);
|
|
11103
|
-
const clear =
|
|
11104
|
-
const isSelected =
|
|
11105
|
-
const value =
|
|
11328
|
+
const clear = useCallback15(() => commit([]), [commit]);
|
|
11329
|
+
const isSelected = useCallback15((id) => selected.includes(id), [selected]);
|
|
11330
|
+
const value = useMemo14(
|
|
11106
11331
|
() => ({ selected, select, deselect, toggle, clear, isSelected }),
|
|
11107
11332
|
[selected, select, deselect, toggle, clear, isSelected]
|
|
11108
11333
|
);
|
|
@@ -11115,10 +11340,10 @@ function useSelection() {
|
|
|
11115
11340
|
}
|
|
11116
11341
|
|
|
11117
11342
|
// src/components/TransformHandles.tsx
|
|
11118
|
-
import { useContext as useContext58, useEffect as
|
|
11343
|
+
import { useContext as useContext58, useEffect as useEffect71, useRef as useRef32 } from "react";
|
|
11119
11344
|
|
|
11120
11345
|
// src/hooks/useOverlayTick.ts
|
|
11121
|
-
import { useEffect as
|
|
11346
|
+
import { useEffect as useEffect70 } from "react";
|
|
11122
11347
|
var callbacks = /* @__PURE__ */ new Set();
|
|
11123
11348
|
var rafId = 0;
|
|
11124
11349
|
function tick() {
|
|
@@ -11141,7 +11366,7 @@ function register(cb) {
|
|
|
11141
11366
|
};
|
|
11142
11367
|
}
|
|
11143
11368
|
function useOverlayTick(callback, deps = []) {
|
|
11144
|
-
|
|
11369
|
+
useEffect70(() => {
|
|
11145
11370
|
return register(callback);
|
|
11146
11371
|
}, deps);
|
|
11147
11372
|
}
|
|
@@ -11157,8 +11382,8 @@ function TransformHandles({
|
|
|
11157
11382
|
}) {
|
|
11158
11383
|
const engine = useContext58(EngineContext);
|
|
11159
11384
|
const selection = useSelection();
|
|
11160
|
-
const overlayRef =
|
|
11161
|
-
const dragRef =
|
|
11385
|
+
const overlayRef = useRef32(null);
|
|
11386
|
+
const dragRef = useRef32(null);
|
|
11162
11387
|
useOverlayTick(() => {
|
|
11163
11388
|
if (!engine) return;
|
|
11164
11389
|
const overlay = overlayRef.current;
|
|
@@ -11193,7 +11418,7 @@ function TransformHandles({
|
|
|
11193
11418
|
node.style.transform = `translate(-50%, -50%) rotate(${t.rotation}rad)`;
|
|
11194
11419
|
}
|
|
11195
11420
|
}, [engine, selection.selected]);
|
|
11196
|
-
|
|
11421
|
+
useEffect71(() => {
|
|
11197
11422
|
if (!engine) return;
|
|
11198
11423
|
const onMove = (e) => {
|
|
11199
11424
|
const drag = dragRef.current;
|
|
@@ -11417,7 +11642,7 @@ function worldToScreenCss(engine, wx, wy) {
|
|
|
11417
11642
|
}
|
|
11418
11643
|
|
|
11419
11644
|
// src/hooks/useSnap.ts
|
|
11420
|
-
import { useCallback as
|
|
11645
|
+
import { useCallback as useCallback16, useContext as useContext59 } from "react";
|
|
11421
11646
|
function useSnap(options) {
|
|
11422
11647
|
const engine = useContext59(EngineContext);
|
|
11423
11648
|
const gridX = typeof options?.grid === "number" ? options.grid : options?.grid?.x ?? 0;
|
|
@@ -11425,7 +11650,7 @@ function useSnap(options) {
|
|
|
11425
11650
|
const snapToEntities = options?.snapToEntities ?? false;
|
|
11426
11651
|
const threshold = options?.threshold ?? 8;
|
|
11427
11652
|
const exclude = options?.exclude;
|
|
11428
|
-
const snapToGrid =
|
|
11653
|
+
const snapToGrid = useCallback16(
|
|
11429
11654
|
(x, y) => {
|
|
11430
11655
|
const sx = gridX > 0 ? Math.round(x / gridX) * gridX : x;
|
|
11431
11656
|
const sy = gridY > 0 ? Math.round(y / gridY) * gridY : y;
|
|
@@ -11433,7 +11658,7 @@ function useSnap(options) {
|
|
|
11433
11658
|
},
|
|
11434
11659
|
[gridX, gridY]
|
|
11435
11660
|
);
|
|
11436
|
-
const snap =
|
|
11661
|
+
const snap = useCallback16(
|
|
11437
11662
|
(x, y) => {
|
|
11438
11663
|
let outX = x;
|
|
11439
11664
|
let outY = y;
|
|
@@ -11508,7 +11733,7 @@ function getBounds(ecs, id) {
|
|
|
11508
11733
|
}
|
|
11509
11734
|
|
|
11510
11735
|
// src/components/EditableText.tsx
|
|
11511
|
-
import { useContext as useContext60, useEffect as
|
|
11736
|
+
import { useContext as useContext60, useEffect as useEffect72, useRef as useRef33 } from "react";
|
|
11512
11737
|
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
11513
11738
|
function EditableText({
|
|
11514
11739
|
value,
|
|
@@ -11532,8 +11757,8 @@ function EditableText({
|
|
|
11532
11757
|
}) {
|
|
11533
11758
|
const engine = useContext60(EngineContext);
|
|
11534
11759
|
const entityId = useContext60(EntityContext);
|
|
11535
|
-
const containerRef =
|
|
11536
|
-
const inputRef =
|
|
11760
|
+
const containerRef = useRef33(null);
|
|
11761
|
+
const inputRef = useRef33(null);
|
|
11537
11762
|
useOverlayTick(() => {
|
|
11538
11763
|
if (!engine || entityId === null || entityId === void 0) return;
|
|
11539
11764
|
const container = containerRef.current;
|
|
@@ -11560,7 +11785,7 @@ function EditableText({
|
|
|
11560
11785
|
container.style.setProperty("--cubeforge-canvas-left", `${rect.left + window.scrollX}px`);
|
|
11561
11786
|
container.style.setProperty("--cubeforge-canvas-top", `${rect.top + window.scrollY}px`);
|
|
11562
11787
|
}, [engine, entityId, width, height, fontSize]);
|
|
11563
|
-
|
|
11788
|
+
useEffect72(() => {
|
|
11564
11789
|
if (autoFocus) inputRef.current?.focus();
|
|
11565
11790
|
}, [autoFocus]);
|
|
11566
11791
|
if (!engine) return null;
|
|
@@ -11691,7 +11916,7 @@ function copyRegion(source, region, scale) {
|
|
|
11691
11916
|
}
|
|
11692
11917
|
|
|
11693
11918
|
// src/components/A11yNode.tsx
|
|
11694
|
-
import { useContext as useContext61, useRef as
|
|
11919
|
+
import { useContext as useContext61, useRef as useRef34 } from "react";
|
|
11695
11920
|
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
11696
11921
|
function A11yNode({
|
|
11697
11922
|
label,
|
|
@@ -11707,7 +11932,7 @@ function A11yNode({
|
|
|
11707
11932
|
}) {
|
|
11708
11933
|
const engine = useContext61(EngineContext);
|
|
11709
11934
|
const entityId = useContext61(EntityContext);
|
|
11710
|
-
const nodeRef =
|
|
11935
|
+
const nodeRef = useRef34(null);
|
|
11711
11936
|
useOverlayTick(() => {
|
|
11712
11937
|
if (!engine || entityId === null || entityId === void 0) return;
|
|
11713
11938
|
const node = nodeRef.current;
|
|
@@ -11796,7 +12021,7 @@ function worldToScreenCss3(engine, wx, wy) {
|
|
|
11796
12021
|
}
|
|
11797
12022
|
|
|
11798
12023
|
// src/components/VectorPath.tsx
|
|
11799
|
-
import { useContext as useContext62, useRef as
|
|
12024
|
+
import { useContext as useContext62, useRef as useRef35 } from "react";
|
|
11800
12025
|
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
11801
12026
|
function VectorPath({
|
|
11802
12027
|
d,
|
|
@@ -11812,7 +12037,7 @@ function VectorPath({
|
|
|
11812
12037
|
}) {
|
|
11813
12038
|
const engine = useContext62(EngineContext);
|
|
11814
12039
|
const entityId = useContext62(EntityContext);
|
|
11815
|
-
const svgRef =
|
|
12040
|
+
const svgRef = useRef35(null);
|
|
11816
12041
|
useOverlayTick(() => {
|
|
11817
12042
|
if (!engine || entityId === null || entityId === void 0) return;
|
|
11818
12043
|
const svg = svgRef.current;
|
|
@@ -11873,12 +12098,12 @@ function worldToScreenCss4(engine, wx, wy) {
|
|
|
11873
12098
|
}
|
|
11874
12099
|
|
|
11875
12100
|
// src/hooks/useGrid.ts
|
|
11876
|
-
import { useCallback as
|
|
12101
|
+
import { useCallback as useCallback17, useContext as useContext63, useMemo as useMemo15, useRef as useRef36, useState as useState17 } from "react";
|
|
11877
12102
|
function useGrid({ width, height, fill }) {
|
|
11878
12103
|
const engine = useContext63(EngineContext);
|
|
11879
12104
|
const [version, setVersion] = useState17(0);
|
|
11880
|
-
const bump =
|
|
11881
|
-
const dataRef =
|
|
12105
|
+
const bump = useCallback17(() => setVersion((v) => v + 1), []);
|
|
12106
|
+
const dataRef = useRef36(null);
|
|
11882
12107
|
if (dataRef.current === null) {
|
|
11883
12108
|
const arr = new Array(width * height);
|
|
11884
12109
|
if (typeof fill === "function") {
|
|
@@ -11893,19 +12118,19 @@ function useGrid({ width, height, fill }) {
|
|
|
11893
12118
|
}
|
|
11894
12119
|
dataRef.current = arr;
|
|
11895
12120
|
}
|
|
11896
|
-
const markChanged =
|
|
12121
|
+
const markChanged = useCallback17(() => {
|
|
11897
12122
|
engine?.loop.markDirty();
|
|
11898
12123
|
bump();
|
|
11899
12124
|
}, [engine, bump]);
|
|
11900
|
-
const inBounds =
|
|
11901
|
-
const get =
|
|
12125
|
+
const inBounds = useCallback17((x, y) => x >= 0 && y >= 0 && x < width && y < height, [width, height]);
|
|
12126
|
+
const get = useCallback17(
|
|
11902
12127
|
(x, y) => {
|
|
11903
12128
|
if (!inBounds(x, y)) return void 0;
|
|
11904
12129
|
return dataRef.current[y * width + x];
|
|
11905
12130
|
},
|
|
11906
12131
|
[width, inBounds]
|
|
11907
12132
|
);
|
|
11908
|
-
const set =
|
|
12133
|
+
const set = useCallback17(
|
|
11909
12134
|
(x, y, value) => {
|
|
11910
12135
|
if (!inBounds(x, y)) return;
|
|
11911
12136
|
const data = dataRef.current;
|
|
@@ -11916,7 +12141,7 @@ function useGrid({ width, height, fill }) {
|
|
|
11916
12141
|
},
|
|
11917
12142
|
[width, inBounds, markChanged]
|
|
11918
12143
|
);
|
|
11919
|
-
const swap =
|
|
12144
|
+
const swap = useCallback17(
|
|
11920
12145
|
(ax, ay, bx, by) => {
|
|
11921
12146
|
if (!inBounds(ax, ay) || !inBounds(bx, by)) return;
|
|
11922
12147
|
const data = dataRef.current;
|
|
@@ -11930,7 +12155,7 @@ function useGrid({ width, height, fill }) {
|
|
|
11930
12155
|
},
|
|
11931
12156
|
[width, inBounds, markChanged]
|
|
11932
12157
|
);
|
|
11933
|
-
const forEach =
|
|
12158
|
+
const forEach = useCallback17(
|
|
11934
12159
|
(cb) => {
|
|
11935
12160
|
const data = dataRef.current;
|
|
11936
12161
|
for (let y = 0; y < height; y++) {
|
|
@@ -11941,7 +12166,7 @@ function useGrid({ width, height, fill }) {
|
|
|
11941
12166
|
},
|
|
11942
12167
|
[width, height]
|
|
11943
12168
|
);
|
|
11944
|
-
const find =
|
|
12169
|
+
const find = useCallback17(
|
|
11945
12170
|
(pred) => {
|
|
11946
12171
|
const data = dataRef.current;
|
|
11947
12172
|
for (let y = 0; y < height; y++) {
|
|
@@ -11954,7 +12179,7 @@ function useGrid({ width, height, fill }) {
|
|
|
11954
12179
|
},
|
|
11955
12180
|
[width, height]
|
|
11956
12181
|
);
|
|
11957
|
-
const count =
|
|
12182
|
+
const count = useCallback17(
|
|
11958
12183
|
(pred) => {
|
|
11959
12184
|
const data = dataRef.current;
|
|
11960
12185
|
let n = 0;
|
|
@@ -11967,7 +12192,7 @@ function useGrid({ width, height, fill }) {
|
|
|
11967
12192
|
},
|
|
11968
12193
|
[width, height]
|
|
11969
12194
|
);
|
|
11970
|
-
const neighbors =
|
|
12195
|
+
const neighbors = useCallback17(
|
|
11971
12196
|
(x, y, diagonal = false) => {
|
|
11972
12197
|
const data = dataRef.current;
|
|
11973
12198
|
const result = [];
|
|
@@ -11995,7 +12220,7 @@ function useGrid({ width, height, fill }) {
|
|
|
11995
12220
|
},
|
|
11996
12221
|
[width, inBounds]
|
|
11997
12222
|
);
|
|
11998
|
-
const fillAll =
|
|
12223
|
+
const fillAll = useCallback17(
|
|
11999
12224
|
(value) => {
|
|
12000
12225
|
const data = dataRef.current;
|
|
12001
12226
|
if (typeof value === "function") {
|
|
@@ -12012,7 +12237,7 @@ function useGrid({ width, height, fill }) {
|
|
|
12012
12237
|
},
|
|
12013
12238
|
[width, height, markChanged]
|
|
12014
12239
|
);
|
|
12015
|
-
const toArray =
|
|
12240
|
+
const toArray = useCallback17(() => {
|
|
12016
12241
|
const data = dataRef.current;
|
|
12017
12242
|
const out = new Array(height);
|
|
12018
12243
|
for (let y = 0; y < height; y++) {
|
|
@@ -12022,7 +12247,7 @@ function useGrid({ width, height, fill }) {
|
|
|
12022
12247
|
}
|
|
12023
12248
|
return out;
|
|
12024
12249
|
}, [width, height]);
|
|
12025
|
-
const fromArray =
|
|
12250
|
+
const fromArray = useCallback17(
|
|
12026
12251
|
(arr) => {
|
|
12027
12252
|
const data = dataRef.current;
|
|
12028
12253
|
for (let y = 0; y < height; y++) {
|
|
@@ -12037,7 +12262,7 @@ function useGrid({ width, height, fill }) {
|
|
|
12037
12262
|
[width, height, markChanged]
|
|
12038
12263
|
);
|
|
12039
12264
|
void version;
|
|
12040
|
-
return
|
|
12265
|
+
return useMemo15(
|
|
12041
12266
|
() => ({
|
|
12042
12267
|
width,
|
|
12043
12268
|
height,
|
|
@@ -12058,7 +12283,7 @@ function useGrid({ width, height, fill }) {
|
|
|
12058
12283
|
}
|
|
12059
12284
|
|
|
12060
12285
|
// src/hooks/useTurnSystem.ts
|
|
12061
|
-
import { useCallback as
|
|
12286
|
+
import { useCallback as useCallback18, useContext as useContext64, useEffect as useEffect73, useMemo as useMemo16, useRef as useRef37, useState as useState18 } from "react";
|
|
12062
12287
|
function useTurnSystem({
|
|
12063
12288
|
players,
|
|
12064
12289
|
initialIndex = 0,
|
|
@@ -12071,11 +12296,11 @@ function useTurnSystem({
|
|
|
12071
12296
|
const [activeIndex, setActiveIndex] = useState18(initialIndex % players.length);
|
|
12072
12297
|
const [turn, setTurn] = useState18(0);
|
|
12073
12298
|
const [isPending, setIsPending] = useState18(false);
|
|
12074
|
-
const pendingRafId =
|
|
12075
|
-
const pendingRemaining =
|
|
12076
|
-
const pendingTarget =
|
|
12077
|
-
const pendingLastTime =
|
|
12078
|
-
const clearPending =
|
|
12299
|
+
const pendingRafId = useRef37(null);
|
|
12300
|
+
const pendingRemaining = useRef37(0);
|
|
12301
|
+
const pendingTarget = useRef37(null);
|
|
12302
|
+
const pendingLastTime = useRef37(0);
|
|
12303
|
+
const clearPending = useCallback18(() => {
|
|
12079
12304
|
if (pendingRafId.current !== null) {
|
|
12080
12305
|
cancelAnimationFrame(pendingRafId.current);
|
|
12081
12306
|
pendingRafId.current = null;
|
|
@@ -12083,13 +12308,13 @@ function useTurnSystem({
|
|
|
12083
12308
|
pendingTarget.current = null;
|
|
12084
12309
|
setIsPending(false);
|
|
12085
12310
|
}, []);
|
|
12086
|
-
const startedOnce =
|
|
12087
|
-
|
|
12311
|
+
const startedOnce = useRef37(false);
|
|
12312
|
+
useEffect73(() => {
|
|
12088
12313
|
if (startedOnce.current) return;
|
|
12089
12314
|
startedOnce.current = true;
|
|
12090
12315
|
onTurnStart?.({ player: players[activeIndex], index: activeIndex, turn: 0 });
|
|
12091
12316
|
}, []);
|
|
12092
|
-
const applyChange =
|
|
12317
|
+
const applyChange = useCallback18(
|
|
12093
12318
|
(nextIndex) => {
|
|
12094
12319
|
const curr = players[activeIndex];
|
|
12095
12320
|
onTurnEnd?.({ player: curr, index: activeIndex, turn });
|
|
@@ -12102,7 +12327,7 @@ function useTurnSystem({
|
|
|
12102
12327
|
},
|
|
12103
12328
|
[players, activeIndex, turn, onTurnStart, onTurnEnd, engine]
|
|
12104
12329
|
);
|
|
12105
|
-
const scheduleChange =
|
|
12330
|
+
const scheduleChange = useCallback18(
|
|
12106
12331
|
(nextIndex) => {
|
|
12107
12332
|
clearPending();
|
|
12108
12333
|
if (aiDelay <= 0) {
|
|
@@ -12134,9 +12359,9 @@ function useTurnSystem({
|
|
|
12134
12359
|
},
|
|
12135
12360
|
[aiDelay, applyChange, clearPending, engine]
|
|
12136
12361
|
);
|
|
12137
|
-
const nextTurn =
|
|
12138
|
-
const prevTurn =
|
|
12139
|
-
const skipTo =
|
|
12362
|
+
const nextTurn = useCallback18(() => scheduleChange(activeIndex + 1), [scheduleChange, activeIndex]);
|
|
12363
|
+
const prevTurn = useCallback18(() => scheduleChange(activeIndex - 1), [scheduleChange, activeIndex]);
|
|
12364
|
+
const skipTo = useCallback18(
|
|
12140
12365
|
(target) => {
|
|
12141
12366
|
let idx;
|
|
12142
12367
|
if (typeof target === "number") {
|
|
@@ -12149,19 +12374,19 @@ function useTurnSystem({
|
|
|
12149
12374
|
},
|
|
12150
12375
|
[players, scheduleChange]
|
|
12151
12376
|
);
|
|
12152
|
-
const reset =
|
|
12377
|
+
const reset = useCallback18(() => {
|
|
12153
12378
|
clearPending();
|
|
12154
12379
|
setActiveIndex(initialIndex % players.length);
|
|
12155
12380
|
setTurn(0);
|
|
12156
12381
|
engine?.loop.markDirty();
|
|
12157
12382
|
}, [players.length, initialIndex, clearPending, engine]);
|
|
12158
|
-
|
|
12383
|
+
useEffect73(
|
|
12159
12384
|
() => () => {
|
|
12160
12385
|
if (pendingRafId.current !== null) cancelAnimationFrame(pendingRafId.current);
|
|
12161
12386
|
},
|
|
12162
12387
|
[]
|
|
12163
12388
|
);
|
|
12164
|
-
return
|
|
12389
|
+
return useMemo16(
|
|
12165
12390
|
() => ({
|
|
12166
12391
|
activePlayer: players[activeIndex],
|
|
12167
12392
|
activeIndex,
|
|
@@ -12177,13 +12402,13 @@ function useTurnSystem({
|
|
|
12177
12402
|
}
|
|
12178
12403
|
|
|
12179
12404
|
// src/hooks/useHoverable.ts
|
|
12180
|
-
import { useContext as useContext65, useEffect as
|
|
12405
|
+
import { useContext as useContext65, useEffect as useEffect74, useState as useState19 } from "react";
|
|
12181
12406
|
function useHoverable(options) {
|
|
12182
12407
|
const engine = useContext65(EngineContext);
|
|
12183
12408
|
const ctxEntityId = useContext65(EntityContext);
|
|
12184
12409
|
const entityId = options?.entityId ?? ctxEntityId;
|
|
12185
12410
|
const [isHovered, setIsHovered] = useState19(false);
|
|
12186
|
-
|
|
12411
|
+
useEffect74(() => {
|
|
12187
12412
|
if (!engine || entityId === null || entityId === void 0 || options?.disabled) return;
|
|
12188
12413
|
const canvas = engine.canvas;
|
|
12189
12414
|
let hovered = false;
|
|
@@ -12260,7 +12485,7 @@ function screenToWorld(engine, cssX, cssY) {
|
|
|
12260
12485
|
}
|
|
12261
12486
|
|
|
12262
12487
|
// src/hooks/useDragDrop.ts
|
|
12263
|
-
import { useContext as useContext66, useEffect as
|
|
12488
|
+
import { useContext as useContext66, useEffect as useEffect75, useRef as useRef38, useState as useState20 } from "react";
|
|
12264
12489
|
var dragStateByEngine = /* @__PURE__ */ new WeakMap();
|
|
12265
12490
|
function getActiveDrag(engine) {
|
|
12266
12491
|
return dragStateByEngine.get(engine) ?? null;
|
|
@@ -12285,9 +12510,9 @@ function useDraggable(options) {
|
|
|
12285
12510
|
const entityId = options?.entityId ?? ctxEntityId;
|
|
12286
12511
|
const [isDragging, setIsDragging] = useState20(false);
|
|
12287
12512
|
const [position, setPosition] = useState20({ x: 0, y: 0 });
|
|
12288
|
-
const optsRef =
|
|
12513
|
+
const optsRef = useRef38(options);
|
|
12289
12514
|
optsRef.current = options;
|
|
12290
|
-
|
|
12515
|
+
useEffect75(() => {
|
|
12291
12516
|
if (!engine || entityId === null || entityId === void 0 || options?.disabled) return;
|
|
12292
12517
|
const canvas = engine.canvas;
|
|
12293
12518
|
let dragging = false;
|
|
@@ -12397,9 +12622,9 @@ function useDroppable(options) {
|
|
|
12397
12622
|
const entityId = options?.entityId ?? ctxEntityId;
|
|
12398
12623
|
const [isOver, setIsOver] = useState20(false);
|
|
12399
12624
|
const [hoveredBy, setHoveredBy] = useState20(null);
|
|
12400
|
-
const optsRef =
|
|
12625
|
+
const optsRef = useRef38(options);
|
|
12401
12626
|
optsRef.current = options;
|
|
12402
|
-
|
|
12627
|
+
useEffect75(() => {
|
|
12403
12628
|
if (!engine || entityId === null || entityId === void 0 || options?.disabled) return;
|
|
12404
12629
|
let currentlyOver = false;
|
|
12405
12630
|
const check = () => {
|
|
@@ -12501,7 +12726,7 @@ function findDroppableUnder(engine, drag) {
|
|
|
12501
12726
|
}
|
|
12502
12727
|
|
|
12503
12728
|
// src/hooks/useKeyboardFocus.ts
|
|
12504
|
-
import { useContext as useContext67, useEffect as
|
|
12729
|
+
import { useContext as useContext67, useEffect as useEffect76, useRef as useRef39, useState as useState21 } from "react";
|
|
12505
12730
|
var registry = /* @__PURE__ */ new Map();
|
|
12506
12731
|
var focusedId = null;
|
|
12507
12732
|
var subscribers = /* @__PURE__ */ new Set();
|
|
@@ -12518,9 +12743,9 @@ function setFocused(id) {
|
|
|
12518
12743
|
}
|
|
12519
12744
|
function useFocusable(options) {
|
|
12520
12745
|
const entityIdCtx = useContext67(EntityContext);
|
|
12521
|
-
const optsRef =
|
|
12746
|
+
const optsRef = useRef39(options);
|
|
12522
12747
|
optsRef.current = options;
|
|
12523
|
-
|
|
12748
|
+
useEffect76(() => {
|
|
12524
12749
|
if (entityIdCtx === null || entityIdCtx === void 0) return;
|
|
12525
12750
|
const id = entityIdCtx;
|
|
12526
12751
|
const entry = {
|
|
@@ -12540,14 +12765,14 @@ function useFocusable(options) {
|
|
|
12540
12765
|
function useKeyboardFocus() {
|
|
12541
12766
|
const engine = useContext67(EngineContext);
|
|
12542
12767
|
const [focused, setFocusedState] = useState21(focusedId);
|
|
12543
|
-
|
|
12768
|
+
useEffect76(() => {
|
|
12544
12769
|
const cb = () => setFocusedState(focusedId);
|
|
12545
12770
|
subscribers.add(cb);
|
|
12546
12771
|
return () => {
|
|
12547
12772
|
subscribers.delete(cb);
|
|
12548
12773
|
};
|
|
12549
12774
|
}, []);
|
|
12550
|
-
|
|
12775
|
+
useEffect76(() => {
|
|
12551
12776
|
if (!engine) return;
|
|
12552
12777
|
const onKey = (e) => {
|
|
12553
12778
|
const target = e.target;
|
|
@@ -12673,7 +12898,7 @@ function subscribeFocus(cb) {
|
|
|
12673
12898
|
}
|
|
12674
12899
|
|
|
12675
12900
|
// src/components/FocusRing.tsx
|
|
12676
|
-
import { useContext as useContext68, useEffect as
|
|
12901
|
+
import { useContext as useContext68, useEffect as useEffect77, useRef as useRef40, useState as useState22 } from "react";
|
|
12677
12902
|
import { Fragment as Fragment9, jsx as jsx20, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
12678
12903
|
function FocusRing({
|
|
12679
12904
|
color = "#4fc3f7",
|
|
@@ -12683,14 +12908,14 @@ function FocusRing({
|
|
|
12683
12908
|
pulse = true
|
|
12684
12909
|
}) {
|
|
12685
12910
|
const engine = useContext68(EngineContext);
|
|
12686
|
-
const ringRef =
|
|
12911
|
+
const ringRef = useRef40(null);
|
|
12687
12912
|
const [focused, setFocused2] = useState22(getFocusedEntityId());
|
|
12688
12913
|
const [reducedMotion, setReducedMotion] = useState22(false);
|
|
12689
|
-
|
|
12914
|
+
useEffect77(() => {
|
|
12690
12915
|
const unsub = subscribeFocus(() => setFocused2(getFocusedEntityId()));
|
|
12691
12916
|
return unsub;
|
|
12692
12917
|
}, []);
|
|
12693
|
-
|
|
12918
|
+
useEffect77(() => {
|
|
12694
12919
|
if (typeof window === "undefined" || !window.matchMedia) return;
|
|
12695
12920
|
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
12696
12921
|
setReducedMotion(mq.matches);
|
|
@@ -12827,10 +13052,10 @@ function listSavedScenes(prefix = "") {
|
|
|
12827
13052
|
}
|
|
12828
13053
|
|
|
12829
13054
|
// ../gameplay/src/hooks/useAnimationController.ts
|
|
12830
|
-
import { useState as useState23, useCallback as
|
|
13055
|
+
import { useState as useState23, useCallback as useCallback19 } from "react";
|
|
12831
13056
|
function useAnimationController(states, initial) {
|
|
12832
13057
|
const [stateName, setStateName] = useState23(initial);
|
|
12833
|
-
const setState =
|
|
13058
|
+
const setState = useCallback19((next) => {
|
|
12834
13059
|
setStateName((prev) => prev === next ? prev : next);
|
|
12835
13060
|
}, []);
|
|
12836
13061
|
const clip = states[stateName] ?? states[initial];
|
|
@@ -12852,39 +13077,39 @@ function useAnimationController(states, initial) {
|
|
|
12852
13077
|
}
|
|
12853
13078
|
|
|
12854
13079
|
// ../gameplay/src/hooks/useAISteering.ts
|
|
12855
|
-
import { useCallback as
|
|
13080
|
+
import { useCallback as useCallback20 } from "react";
|
|
12856
13081
|
function useAISteering() {
|
|
12857
|
-
const seek$ =
|
|
12858
|
-
const flee$ =
|
|
12859
|
-
const arrive$ =
|
|
13082
|
+
const seek$ = useCallback20((pos, target, speed) => seek(pos, target, speed), []);
|
|
13083
|
+
const flee$ = useCallback20((pos, threat, speed) => flee(pos, threat, speed), []);
|
|
13084
|
+
const arrive$ = useCallback20(
|
|
12860
13085
|
(pos, target, speed, slowRadius) => arrive(pos, target, speed, slowRadius),
|
|
12861
13086
|
[]
|
|
12862
13087
|
);
|
|
12863
|
-
const patrol$ =
|
|
13088
|
+
const patrol$ = useCallback20(
|
|
12864
13089
|
(pos, waypoints, speed, currentIdx, arriveThreshold) => patrol(pos, waypoints, speed, currentIdx, arriveThreshold),
|
|
12865
13090
|
[]
|
|
12866
13091
|
);
|
|
12867
|
-
const wander$ =
|
|
13092
|
+
const wander$ = useCallback20(
|
|
12868
13093
|
(pos, angle, speed, jitter) => wander(pos, angle, speed, jitter),
|
|
12869
13094
|
[]
|
|
12870
13095
|
);
|
|
12871
|
-
const pursuit$ =
|
|
13096
|
+
const pursuit$ = useCallback20(
|
|
12872
13097
|
(pos, targetPos, targetVel, speed, lookAhead) => pursuit(pos, targetPos, targetVel, speed, lookAhead),
|
|
12873
13098
|
[]
|
|
12874
13099
|
);
|
|
12875
|
-
const evade$ =
|
|
13100
|
+
const evade$ = useCallback20(
|
|
12876
13101
|
(pos, threatPos, threatVel, speed, lookAhead) => evade(pos, threatPos, threatVel, speed, lookAhead),
|
|
12877
13102
|
[]
|
|
12878
13103
|
);
|
|
12879
|
-
const separation$ =
|
|
13104
|
+
const separation$ = useCallback20(
|
|
12880
13105
|
(pos, neighbors, speed, radius) => separation(pos, neighbors, speed, radius),
|
|
12881
13106
|
[]
|
|
12882
13107
|
);
|
|
12883
|
-
const cohesion$ =
|
|
13108
|
+
const cohesion$ = useCallback20(
|
|
12884
13109
|
(pos, neighbors, speed) => cohesion(pos, neighbors, speed),
|
|
12885
13110
|
[]
|
|
12886
13111
|
);
|
|
12887
|
-
const alignment$ =
|
|
13112
|
+
const alignment$ = useCallback20(
|
|
12888
13113
|
(neighborVelocities, speed) => alignment(neighborVelocities, speed),
|
|
12889
13114
|
[]
|
|
12890
13115
|
);
|
|
@@ -12915,11 +13140,11 @@ function useDamageZone(damage, opts = {}) {
|
|
|
12915
13140
|
}
|
|
12916
13141
|
|
|
12917
13142
|
// ../gameplay/src/hooks/useDropThrough.ts
|
|
12918
|
-
import { useContext as useContext70, useCallback as
|
|
13143
|
+
import { useContext as useContext70, useCallback as useCallback21 } from "react";
|
|
12919
13144
|
function useDropThrough(frames = 8) {
|
|
12920
13145
|
const engine = useContext70(EngineContext);
|
|
12921
13146
|
const entityId = useContext70(EntityContext);
|
|
12922
|
-
const dropThrough =
|
|
13147
|
+
const dropThrough = useCallback21(() => {
|
|
12923
13148
|
const rb = engine.ecs.getComponent(entityId, "RigidBody");
|
|
12924
13149
|
if (rb) rb.dropThrough = frames;
|
|
12925
13150
|
}, [engine.ecs, entityId, frames]);
|
|
@@ -12927,17 +13152,17 @@ function useDropThrough(frames = 8) {
|
|
|
12927
13152
|
}
|
|
12928
13153
|
|
|
12929
13154
|
// ../gameplay/src/hooks/useGameStateMachine.ts
|
|
12930
|
-
import { useState as useState24, useRef as
|
|
13155
|
+
import { useState as useState24, useRef as useRef41, useCallback as useCallback22, useEffect as useEffect78, useContext as useContext71 } from "react";
|
|
12931
13156
|
function useGameStateMachine(states, initial) {
|
|
12932
13157
|
const engine = useContext71(EngineContext);
|
|
12933
13158
|
const [state, setState] = useState24(initial);
|
|
12934
|
-
const stateRef =
|
|
12935
|
-
const statesRef =
|
|
13159
|
+
const stateRef = useRef41(initial);
|
|
13160
|
+
const statesRef = useRef41(states);
|
|
12936
13161
|
statesRef.current = states;
|
|
12937
|
-
|
|
13162
|
+
useEffect78(() => {
|
|
12938
13163
|
statesRef.current[initial]?.onEnter?.();
|
|
12939
13164
|
}, []);
|
|
12940
|
-
const transition =
|
|
13165
|
+
const transition = useCallback22((to) => {
|
|
12941
13166
|
const current = stateRef.current;
|
|
12942
13167
|
if (current === to) return;
|
|
12943
13168
|
statesRef.current[current]?.onExit?.();
|
|
@@ -12945,7 +13170,7 @@ function useGameStateMachine(states, initial) {
|
|
|
12945
13170
|
setState(to);
|
|
12946
13171
|
statesRef.current[to]?.onEnter?.();
|
|
12947
13172
|
}, []);
|
|
12948
|
-
|
|
13173
|
+
useEffect78(() => {
|
|
12949
13174
|
const eid = engine.ecs.createEntity();
|
|
12950
13175
|
engine.ecs.addComponent(
|
|
12951
13176
|
eid,
|
|
@@ -12961,27 +13186,27 @@ function useGameStateMachine(states, initial) {
|
|
|
12961
13186
|
}
|
|
12962
13187
|
|
|
12963
13188
|
// ../gameplay/src/hooks/useHealth.ts
|
|
12964
|
-
import { useRef as
|
|
13189
|
+
import { useRef as useRef42, useEffect as useEffect79, useContext as useContext72, useCallback as useCallback23 } from "react";
|
|
12965
13190
|
function useHealth(maxHp, opts = {}) {
|
|
12966
13191
|
const engine = useContext72(EngineContext);
|
|
12967
13192
|
const entityId = useContext72(EntityContext);
|
|
12968
|
-
const hpRef =
|
|
12969
|
-
const invincibleRef =
|
|
13193
|
+
const hpRef = useRef42(maxHp);
|
|
13194
|
+
const invincibleRef = useRef42(false);
|
|
12970
13195
|
const iFrameDuration = opts.iFrames ?? 1;
|
|
12971
|
-
const onDeathRef =
|
|
12972
|
-
const onDamageRef =
|
|
12973
|
-
|
|
13196
|
+
const onDeathRef = useRef42(opts.onDeath);
|
|
13197
|
+
const onDamageRef = useRef42(opts.onDamage);
|
|
13198
|
+
useEffect79(() => {
|
|
12974
13199
|
onDeathRef.current = opts.onDeath;
|
|
12975
13200
|
});
|
|
12976
|
-
|
|
13201
|
+
useEffect79(() => {
|
|
12977
13202
|
onDamageRef.current = opts.onDamage;
|
|
12978
13203
|
});
|
|
12979
|
-
const timerRef =
|
|
13204
|
+
const timerRef = useRef42(
|
|
12980
13205
|
createTimer(iFrameDuration, () => {
|
|
12981
13206
|
invincibleRef.current = false;
|
|
12982
13207
|
})
|
|
12983
13208
|
);
|
|
12984
|
-
const takeDamage =
|
|
13209
|
+
const takeDamage = useCallback23(
|
|
12985
13210
|
(amount = 1) => {
|
|
12986
13211
|
if (invincibleRef.current || hpRef.current <= 0) return;
|
|
12987
13212
|
hpRef.current = Math.max(0, hpRef.current - amount);
|
|
@@ -12994,28 +13219,28 @@ function useHealth(maxHp, opts = {}) {
|
|
|
12994
13219
|
},
|
|
12995
13220
|
[iFrameDuration]
|
|
12996
13221
|
);
|
|
12997
|
-
const takeDamageRef =
|
|
12998
|
-
|
|
13222
|
+
const takeDamageRef = useRef42(takeDamage);
|
|
13223
|
+
useEffect79(() => {
|
|
12999
13224
|
takeDamageRef.current = takeDamage;
|
|
13000
13225
|
}, [takeDamage]);
|
|
13001
|
-
|
|
13226
|
+
useEffect79(() => {
|
|
13002
13227
|
return engine.events.on(`damage:${entityId}`, ({ amount }) => {
|
|
13003
13228
|
takeDamageRef.current(amount);
|
|
13004
13229
|
});
|
|
13005
13230
|
}, [engine.events, entityId]);
|
|
13006
|
-
const heal =
|
|
13231
|
+
const heal = useCallback23(
|
|
13007
13232
|
(amount) => {
|
|
13008
13233
|
hpRef.current = Math.min(maxHp, hpRef.current + amount);
|
|
13009
13234
|
},
|
|
13010
13235
|
[maxHp]
|
|
13011
13236
|
);
|
|
13012
|
-
const setHp =
|
|
13237
|
+
const setHp = useCallback23(
|
|
13013
13238
|
(hp) => {
|
|
13014
13239
|
hpRef.current = Math.min(maxHp, Math.max(0, hp));
|
|
13015
13240
|
},
|
|
13016
13241
|
[maxHp]
|
|
13017
13242
|
);
|
|
13018
|
-
const update =
|
|
13243
|
+
const update = useCallback23((dt) => {
|
|
13019
13244
|
timerRef.current.update(dt);
|
|
13020
13245
|
}, []);
|
|
13021
13246
|
return {
|
|
@@ -13039,11 +13264,11 @@ function useHealth(maxHp, opts = {}) {
|
|
|
13039
13264
|
}
|
|
13040
13265
|
|
|
13041
13266
|
// ../gameplay/src/hooks/useKinematicBody.ts
|
|
13042
|
-
import { useContext as useContext73, useCallback as
|
|
13267
|
+
import { useContext as useContext73, useCallback as useCallback24 } from "react";
|
|
13043
13268
|
function useKinematicBody() {
|
|
13044
13269
|
const engine = useContext73(EngineContext);
|
|
13045
13270
|
const entityId = useContext73(EntityContext);
|
|
13046
|
-
const moveAndCollide =
|
|
13271
|
+
const moveAndCollide = useCallback24(
|
|
13047
13272
|
(dx, dy) => {
|
|
13048
13273
|
const transform = engine.ecs.getComponent(entityId, "Transform");
|
|
13049
13274
|
if (!transform) return { dx: 0, dy: 0 };
|
|
@@ -13079,7 +13304,7 @@ function useKinematicBody() {
|
|
|
13079
13304
|
},
|
|
13080
13305
|
[engine.ecs, entityId]
|
|
13081
13306
|
);
|
|
13082
|
-
const setVelocity =
|
|
13307
|
+
const setVelocity = useCallback24(
|
|
13083
13308
|
(vx, vy) => {
|
|
13084
13309
|
const rb = engine.ecs.getComponent(entityId, "RigidBody");
|
|
13085
13310
|
if (rb) {
|
|
@@ -13089,7 +13314,7 @@ function useKinematicBody() {
|
|
|
13089
13314
|
},
|
|
13090
13315
|
[engine.ecs, entityId]
|
|
13091
13316
|
);
|
|
13092
|
-
const setAngularVelocity =
|
|
13317
|
+
const setAngularVelocity = useCallback24(
|
|
13093
13318
|
(w) => {
|
|
13094
13319
|
const rb = engine.ecs.getComponent(entityId, "RigidBody");
|
|
13095
13320
|
if (rb) rb.angularVelocity = w;
|
|
@@ -13100,12 +13325,12 @@ function useKinematicBody() {
|
|
|
13100
13325
|
}
|
|
13101
13326
|
|
|
13102
13327
|
// ../gameplay/src/hooks/useLevelTransition.ts
|
|
13103
|
-
import { useState as useState25, useRef as
|
|
13328
|
+
import { useState as useState25, useRef as useRef43, useCallback as useCallback25 } from "react";
|
|
13104
13329
|
function useLevelTransition(initial) {
|
|
13105
13330
|
const [currentLevel, setCurrentLevel] = useState25(initial);
|
|
13106
13331
|
const [isTransitioning, setIsTransitioning] = useState25(false);
|
|
13107
|
-
const overlayRef =
|
|
13108
|
-
const transitionTo =
|
|
13332
|
+
const overlayRef = useRef43(null);
|
|
13333
|
+
const transitionTo = useCallback25((level, opts = {}) => {
|
|
13109
13334
|
const { duration = 0.4, type = "fade" } = opts;
|
|
13110
13335
|
if (type === "instant") {
|
|
13111
13336
|
setCurrentLevel(level);
|
|
@@ -13142,7 +13367,7 @@ function useLevelTransition(initial) {
|
|
|
13142
13367
|
}
|
|
13143
13368
|
|
|
13144
13369
|
// ../gameplay/src/hooks/usePlatformerController.ts
|
|
13145
|
-
import { useContext as useContext74, useEffect as
|
|
13370
|
+
import { useContext as useContext74, useEffect as useEffect80 } from "react";
|
|
13146
13371
|
function normalizeKeys(val, defaults) {
|
|
13147
13372
|
if (!val) return defaults;
|
|
13148
13373
|
return Array.isArray(val) ? val : [val];
|
|
@@ -13166,7 +13391,7 @@ function usePlatformerController(entityId, opts = {}) {
|
|
|
13166
13391
|
const leftKeys = normalizeKeys(bindings?.left, ["ArrowLeft", "KeyA", "a"]);
|
|
13167
13392
|
const rightKeys = normalizeKeys(bindings?.right, ["ArrowRight", "KeyD", "d"]);
|
|
13168
13393
|
const jumpKeys = normalizeKeys(bindings?.jump, ["Space", "ArrowUp", "KeyW", "w"]);
|
|
13169
|
-
|
|
13394
|
+
useEffect80(() => {
|
|
13170
13395
|
const state = {
|
|
13171
13396
|
coyoteTimer: 0,
|
|
13172
13397
|
jumpBuffer: 0,
|
|
@@ -13230,22 +13455,22 @@ function usePlatformerController(entityId, opts = {}) {
|
|
|
13230
13455
|
}
|
|
13231
13456
|
|
|
13232
13457
|
// ../gameplay/src/hooks/usePathfinding.ts
|
|
13233
|
-
import { useCallback as
|
|
13458
|
+
import { useCallback as useCallback26 } from "react";
|
|
13234
13459
|
function usePathfinding() {
|
|
13235
|
-
const createGrid$ =
|
|
13460
|
+
const createGrid$ = useCallback26(
|
|
13236
13461
|
(cols, rows, cellSize) => createNavGrid(cols, rows, cellSize),
|
|
13237
13462
|
[]
|
|
13238
13463
|
);
|
|
13239
|
-
const setWalkable$ =
|
|
13464
|
+
const setWalkable$ = useCallback26(
|
|
13240
13465
|
(grid, col, row, walkable) => setWalkable(grid, col, row, walkable),
|
|
13241
13466
|
[]
|
|
13242
13467
|
);
|
|
13243
|
-
const findPath$ =
|
|
13468
|
+
const findPath$ = useCallback26((grid, start2, goal) => findPath(grid, start2, goal), []);
|
|
13244
13469
|
return { createGrid: createGrid$, setWalkable: setWalkable$, findPath: findPath$ };
|
|
13245
13470
|
}
|
|
13246
13471
|
|
|
13247
13472
|
// ../gameplay/src/hooks/usePersistedBindings.ts
|
|
13248
|
-
import { useState as useState26, useCallback as
|
|
13473
|
+
import { useState as useState26, useCallback as useCallback27, useMemo as useMemo17, useContext as useContext75 } from "react";
|
|
13249
13474
|
function usePersistedBindings(storageKey, defaults) {
|
|
13250
13475
|
const engine = useContext75(EngineContext);
|
|
13251
13476
|
const input = engine.input;
|
|
@@ -13257,7 +13482,7 @@ function usePersistedBindings(storageKey, defaults) {
|
|
|
13257
13482
|
}
|
|
13258
13483
|
return defaults;
|
|
13259
13484
|
});
|
|
13260
|
-
const normalized =
|
|
13485
|
+
const normalized = useMemo17(() => {
|
|
13261
13486
|
const out = {};
|
|
13262
13487
|
for (const [action, keys] of Object.entries(bindings)) {
|
|
13263
13488
|
if (typeof keys === "string") out[action] = [keys];
|
|
@@ -13265,7 +13490,7 @@ function usePersistedBindings(storageKey, defaults) {
|
|
|
13265
13490
|
}
|
|
13266
13491
|
return out;
|
|
13267
13492
|
}, [bindings]);
|
|
13268
|
-
const rebind =
|
|
13493
|
+
const rebind = useCallback27(
|
|
13269
13494
|
(action, keys) => {
|
|
13270
13495
|
setBindings((prev) => {
|
|
13271
13496
|
const next = { ...prev, [action]: Array.isArray(keys) ? keys : [keys] };
|
|
@@ -13278,14 +13503,14 @@ function usePersistedBindings(storageKey, defaults) {
|
|
|
13278
13503
|
},
|
|
13279
13504
|
[storageKey]
|
|
13280
13505
|
);
|
|
13281
|
-
const reset =
|
|
13506
|
+
const reset = useCallback27(() => {
|
|
13282
13507
|
try {
|
|
13283
13508
|
localStorage.removeItem(storageKey);
|
|
13284
13509
|
} catch {
|
|
13285
13510
|
}
|
|
13286
13511
|
setBindings(defaults);
|
|
13287
13512
|
}, [storageKey]);
|
|
13288
|
-
return
|
|
13513
|
+
return useMemo17(
|
|
13289
13514
|
() => ({
|
|
13290
13515
|
bindings,
|
|
13291
13516
|
rebind,
|
|
@@ -13299,21 +13524,21 @@ function usePersistedBindings(storageKey, defaults) {
|
|
|
13299
13524
|
}
|
|
13300
13525
|
|
|
13301
13526
|
// ../gameplay/src/hooks/useRestart.ts
|
|
13302
|
-
import { useState as useState27, useCallback as
|
|
13527
|
+
import { useState as useState27, useCallback as useCallback28 } from "react";
|
|
13303
13528
|
function useRestart() {
|
|
13304
13529
|
const [restartKey, setRestartKey] = useState27(0);
|
|
13305
|
-
const restart =
|
|
13530
|
+
const restart = useCallback28(() => {
|
|
13306
13531
|
setRestartKey((k) => k + 1);
|
|
13307
13532
|
}, []);
|
|
13308
13533
|
return { restartKey, restart };
|
|
13309
13534
|
}
|
|
13310
13535
|
|
|
13311
13536
|
// ../gameplay/src/hooks/useSave.ts
|
|
13312
|
-
import { useCallback as
|
|
13537
|
+
import { useCallback as useCallback29, useRef as useRef44 } from "react";
|
|
13313
13538
|
function useSave(key, defaultValue, opts = {}) {
|
|
13314
13539
|
const version = opts.version ?? 1;
|
|
13315
|
-
const dataRef =
|
|
13316
|
-
const save =
|
|
13540
|
+
const dataRef = useRef44(defaultValue);
|
|
13541
|
+
const save = useCallback29(
|
|
13317
13542
|
(value) => {
|
|
13318
13543
|
dataRef.current = value;
|
|
13319
13544
|
const slot = { version, data: value };
|
|
@@ -13325,7 +13550,7 @@ function useSave(key, defaultValue, opts = {}) {
|
|
|
13325
13550
|
},
|
|
13326
13551
|
[key, version]
|
|
13327
13552
|
);
|
|
13328
|
-
const load =
|
|
13553
|
+
const load = useCallback29(() => {
|
|
13329
13554
|
try {
|
|
13330
13555
|
const raw = localStorage.getItem(key);
|
|
13331
13556
|
if (!raw) return defaultValue;
|
|
@@ -13345,11 +13570,11 @@ function useSave(key, defaultValue, opts = {}) {
|
|
|
13345
13570
|
return defaultValue;
|
|
13346
13571
|
}
|
|
13347
13572
|
}, [key, version]);
|
|
13348
|
-
const clear =
|
|
13573
|
+
const clear = useCallback29(() => {
|
|
13349
13574
|
localStorage.removeItem(key);
|
|
13350
13575
|
dataRef.current = defaultValue;
|
|
13351
13576
|
}, [key]);
|
|
13352
|
-
const exists =
|
|
13577
|
+
const exists = useCallback29(() => {
|
|
13353
13578
|
return localStorage.getItem(key) !== null;
|
|
13354
13579
|
}, [key]);
|
|
13355
13580
|
return {
|
|
@@ -13364,7 +13589,7 @@ function useSave(key, defaultValue, opts = {}) {
|
|
|
13364
13589
|
}
|
|
13365
13590
|
|
|
13366
13591
|
// ../gameplay/src/hooks/useIDBSave.ts
|
|
13367
|
-
import { useCallback as
|
|
13592
|
+
import { useCallback as useCallback30, useRef as useRef45 } from "react";
|
|
13368
13593
|
var DB_NAME = "cubeforge-saves";
|
|
13369
13594
|
var STORE_NAME = "saves";
|
|
13370
13595
|
function openDB() {
|
|
@@ -13382,12 +13607,12 @@ function openDB() {
|
|
|
13382
13607
|
}
|
|
13383
13608
|
function useIDBSave(key, defaultValue, opts = {}) {
|
|
13384
13609
|
const version = opts.version ?? 1;
|
|
13385
|
-
const dbRef =
|
|
13386
|
-
const getDB =
|
|
13610
|
+
const dbRef = useRef45(null);
|
|
13611
|
+
const getDB = useCallback30(() => {
|
|
13387
13612
|
if (!dbRef.current) dbRef.current = openDB();
|
|
13388
13613
|
return dbRef.current;
|
|
13389
13614
|
}, []);
|
|
13390
|
-
const save =
|
|
13615
|
+
const save = useCallback30(
|
|
13391
13616
|
async (value) => {
|
|
13392
13617
|
const db = await getDB();
|
|
13393
13618
|
const slot = { version, data: value };
|
|
@@ -13400,7 +13625,7 @@ function useIDBSave(key, defaultValue, opts = {}) {
|
|
|
13400
13625
|
},
|
|
13401
13626
|
[getDB, key, version]
|
|
13402
13627
|
);
|
|
13403
|
-
const load =
|
|
13628
|
+
const load = useCallback30(async () => {
|
|
13404
13629
|
const db = await getDB();
|
|
13405
13630
|
return new Promise((resolve, reject) => {
|
|
13406
13631
|
const tx = db.transaction(STORE_NAME, "readonly");
|
|
@@ -13426,7 +13651,7 @@ function useIDBSave(key, defaultValue, opts = {}) {
|
|
|
13426
13651
|
req.onerror = () => reject(req.error);
|
|
13427
13652
|
});
|
|
13428
13653
|
}, [getDB, key, version]);
|
|
13429
|
-
const clear =
|
|
13654
|
+
const clear = useCallback30(async () => {
|
|
13430
13655
|
const db = await getDB();
|
|
13431
13656
|
return new Promise((resolve, reject) => {
|
|
13432
13657
|
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
@@ -13435,7 +13660,7 @@ function useIDBSave(key, defaultValue, opts = {}) {
|
|
|
13435
13660
|
req.onerror = () => reject(req.error);
|
|
13436
13661
|
});
|
|
13437
13662
|
}, [getDB, key]);
|
|
13438
|
-
const exists =
|
|
13663
|
+
const exists = useCallback30(async () => {
|
|
13439
13664
|
const db = await getDB();
|
|
13440
13665
|
return new Promise((resolve, reject) => {
|
|
13441
13666
|
const tx = db.transaction(STORE_NAME, "readonly");
|
|
@@ -13448,7 +13673,7 @@ function useIDBSave(key, defaultValue, opts = {}) {
|
|
|
13448
13673
|
}
|
|
13449
13674
|
|
|
13450
13675
|
// ../gameplay/src/hooks/useSaveSlots.ts
|
|
13451
|
-
import { useCallback as
|
|
13676
|
+
import { useCallback as useCallback31, useState as useState28 } from "react";
|
|
13452
13677
|
function useSaveSlots(namespace, opts = {}) {
|
|
13453
13678
|
const version = opts.version ?? 1;
|
|
13454
13679
|
const indexKey = `cubeforge-saves:${namespace}:__index`;
|
|
@@ -13502,7 +13727,7 @@ function useSaveSlots(namespace, opts = {}) {
|
|
|
13502
13727
|
const metas = readIndex().map((id) => readSlot(id)?.meta).filter((m) => m !== void 0).sort((a, b) => a.savedAt < b.savedAt ? 1 : -1);
|
|
13503
13728
|
setSlots(metas);
|
|
13504
13729
|
}
|
|
13505
|
-
const save =
|
|
13730
|
+
const save = useCallback31(
|
|
13506
13731
|
(id, data, label, thumbnail) => {
|
|
13507
13732
|
const meta = {
|
|
13508
13733
|
id,
|
|
@@ -13517,7 +13742,7 @@ function useSaveSlots(namespace, opts = {}) {
|
|
|
13517
13742
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
13518
13743
|
[namespace, version]
|
|
13519
13744
|
);
|
|
13520
|
-
const load =
|
|
13745
|
+
const load = useCallback31(
|
|
13521
13746
|
(id) => {
|
|
13522
13747
|
const entry = readSlot(id);
|
|
13523
13748
|
if (!entry) return null;
|
|
@@ -13533,7 +13758,7 @@ function useSaveSlots(namespace, opts = {}) {
|
|
|
13533
13758
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
13534
13759
|
[namespace, version]
|
|
13535
13760
|
);
|
|
13536
|
-
const deleteFn =
|
|
13761
|
+
const deleteFn = useCallback31(
|
|
13537
13762
|
(id) => {
|
|
13538
13763
|
try {
|
|
13539
13764
|
localStorage.removeItem(slotKey(id));
|
|
@@ -13545,7 +13770,7 @@ function useSaveSlots(namespace, opts = {}) {
|
|
|
13545
13770
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
13546
13771
|
[namespace]
|
|
13547
13772
|
);
|
|
13548
|
-
const copy =
|
|
13773
|
+
const copy = useCallback31(
|
|
13549
13774
|
(fromId, toId) => {
|
|
13550
13775
|
const entry = readSlot(fromId);
|
|
13551
13776
|
if (!entry) return false;
|
|
@@ -13558,7 +13783,7 @@ function useSaveSlots(namespace, opts = {}) {
|
|
|
13558
13783
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
13559
13784
|
[namespace, version]
|
|
13560
13785
|
);
|
|
13561
|
-
const rename =
|
|
13786
|
+
const rename = useCallback31(
|
|
13562
13787
|
(id, label) => {
|
|
13563
13788
|
const entry = readSlot(id);
|
|
13564
13789
|
if (!entry) return;
|
|
@@ -13568,10 +13793,10 @@ function useSaveSlots(namespace, opts = {}) {
|
|
|
13568
13793
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
13569
13794
|
[namespace]
|
|
13570
13795
|
);
|
|
13571
|
-
const listSlots =
|
|
13796
|
+
const listSlots = useCallback31(() => {
|
|
13572
13797
|
return readIndex().map((id) => readSlot(id)?.meta).filter((m) => m !== void 0).sort((a, b) => a.savedAt < b.savedAt ? 1 : -1);
|
|
13573
13798
|
}, [namespace]);
|
|
13574
|
-
const exists =
|
|
13799
|
+
const exists = useCallback31(
|
|
13575
13800
|
(id) => {
|
|
13576
13801
|
return readSlot(id) !== null;
|
|
13577
13802
|
},
|
|
@@ -13593,7 +13818,7 @@ function useSaveSlots(namespace, opts = {}) {
|
|
|
13593
13818
|
}
|
|
13594
13819
|
|
|
13595
13820
|
// ../gameplay/src/hooks/useTopDownMovement.ts
|
|
13596
|
-
import { useContext as useContext76, useEffect as
|
|
13821
|
+
import { useContext as useContext76, useEffect as useEffect81 } from "react";
|
|
13597
13822
|
function moveToward(current, target, maxDelta) {
|
|
13598
13823
|
const diff = target - current;
|
|
13599
13824
|
if (Math.abs(diff) <= maxDelta) return target;
|
|
@@ -13602,7 +13827,7 @@ function moveToward(current, target, maxDelta) {
|
|
|
13602
13827
|
function useTopDownMovement(entityId, opts = {}) {
|
|
13603
13828
|
const engine = useContext76(EngineContext);
|
|
13604
13829
|
const { speed = 200, normalizeDiagonal = true, acceleration = Infinity, deceleration = acceleration } = opts;
|
|
13605
|
-
|
|
13830
|
+
useEffect81(() => {
|
|
13606
13831
|
const updateFn = (id, world, input, dt) => {
|
|
13607
13832
|
if (!world.hasEntity(id)) return;
|
|
13608
13833
|
const rb = world.getComponent(id, "RigidBody");
|
|
@@ -13642,18 +13867,18 @@ function useTopDownMovement(entityId, opts = {}) {
|
|
|
13642
13867
|
}
|
|
13643
13868
|
|
|
13644
13869
|
// ../gameplay/src/hooks/useDialogue.ts
|
|
13645
|
-
import { useState as useState29, useCallback as
|
|
13870
|
+
import { useState as useState29, useCallback as useCallback32, useRef as useRef46 } from "react";
|
|
13646
13871
|
function useDialogue() {
|
|
13647
13872
|
const [active, setActive] = useState29(false);
|
|
13648
13873
|
const [currentId, setCurrentId] = useState29(null);
|
|
13649
|
-
const scriptRef =
|
|
13650
|
-
const start2 =
|
|
13874
|
+
const scriptRef = useRef46(null);
|
|
13875
|
+
const start2 = useCallback32((script, startId) => {
|
|
13651
13876
|
scriptRef.current = script;
|
|
13652
13877
|
const id = startId ?? Object.keys(script)[0];
|
|
13653
13878
|
setCurrentId(id);
|
|
13654
13879
|
setActive(true);
|
|
13655
13880
|
}, []);
|
|
13656
|
-
const advance =
|
|
13881
|
+
const advance = useCallback32(
|
|
13657
13882
|
(choiceIndex) => {
|
|
13658
13883
|
if (!scriptRef.current || !currentId) return;
|
|
13659
13884
|
const line = scriptRef.current[currentId];
|
|
@@ -13683,7 +13908,7 @@ function useDialogue() {
|
|
|
13683
13908
|
},
|
|
13684
13909
|
[currentId]
|
|
13685
13910
|
);
|
|
13686
|
-
const close =
|
|
13911
|
+
const close = useCallback32(() => {
|
|
13687
13912
|
setActive(false);
|
|
13688
13913
|
setCurrentId(null);
|
|
13689
13914
|
scriptRef.current = null;
|
|
@@ -13693,7 +13918,7 @@ function useDialogue() {
|
|
|
13693
13918
|
}
|
|
13694
13919
|
|
|
13695
13920
|
// ../gameplay/src/hooks/useDialogueTree.ts
|
|
13696
|
-
import { useState as useState30, useCallback as
|
|
13921
|
+
import { useState as useState30, useCallback as useCallback33, useRef as useRef47 } from "react";
|
|
13697
13922
|
function interpolate(text, vars) {
|
|
13698
13923
|
return text.replace(/\{(\w+)\}/g, (_, key) => {
|
|
13699
13924
|
const val = vars[key];
|
|
@@ -13711,8 +13936,8 @@ function useDialogueTree() {
|
|
|
13711
13936
|
const [active, setActive] = useState30(false);
|
|
13712
13937
|
const [currentId, setCurrentId] = useState30(null);
|
|
13713
13938
|
const [variables, setVariables] = useState30({});
|
|
13714
|
-
const scriptRef =
|
|
13715
|
-
const varsRef =
|
|
13939
|
+
const scriptRef = useRef47(null);
|
|
13940
|
+
const varsRef = useRef47({});
|
|
13716
13941
|
function setCurrentNode(id) {
|
|
13717
13942
|
if (!id || !scriptRef.current) {
|
|
13718
13943
|
setActive(false);
|
|
@@ -13728,7 +13953,7 @@ function useDialogueTree() {
|
|
|
13728
13953
|
node.onEnter?.(varsRef.current);
|
|
13729
13954
|
setCurrentId(id);
|
|
13730
13955
|
}
|
|
13731
|
-
const start2 =
|
|
13956
|
+
const start2 = useCallback33(
|
|
13732
13957
|
(script, startId, initialVars) => {
|
|
13733
13958
|
scriptRef.current = script;
|
|
13734
13959
|
const newVars = { ...varsRef.current, ...initialVars };
|
|
@@ -13741,7 +13966,7 @@ function useDialogueTree() {
|
|
|
13741
13966
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
13742
13967
|
[]
|
|
13743
13968
|
);
|
|
13744
|
-
const advance =
|
|
13969
|
+
const advance = useCallback33(
|
|
13745
13970
|
(choiceIndex) => {
|
|
13746
13971
|
if (!scriptRef.current || !currentId) return;
|
|
13747
13972
|
const node = scriptRef.current[currentId];
|
|
@@ -13780,7 +14005,7 @@ function useDialogueTree() {
|
|
|
13780
14005
|
},
|
|
13781
14006
|
[currentId]
|
|
13782
14007
|
);
|
|
13783
|
-
const jumpTo =
|
|
14008
|
+
const jumpTo = useCallback33(
|
|
13784
14009
|
(id) => {
|
|
13785
14010
|
if (!scriptRef.current?.[id]) return;
|
|
13786
14011
|
const current2 = scriptRef.current[currentId ?? ""];
|
|
@@ -13789,11 +14014,11 @@ function useDialogueTree() {
|
|
|
13789
14014
|
},
|
|
13790
14015
|
[currentId]
|
|
13791
14016
|
);
|
|
13792
|
-
const setVar =
|
|
14017
|
+
const setVar = useCallback33((key, value) => {
|
|
13793
14018
|
varsRef.current = { ...varsRef.current, [key]: value };
|
|
13794
14019
|
setVariables({ ...varsRef.current });
|
|
13795
14020
|
}, []);
|
|
13796
|
-
const close =
|
|
14021
|
+
const close = useCallback33(() => {
|
|
13797
14022
|
if (scriptRef.current && currentId) {
|
|
13798
14023
|
scriptRef.current[currentId]?.onExit?.(varsRef.current);
|
|
13799
14024
|
}
|
|
@@ -13819,7 +14044,7 @@ function useDialogueTree() {
|
|
|
13819
14044
|
}
|
|
13820
14045
|
|
|
13821
14046
|
// ../gameplay/src/hooks/useBehaviorTree.ts
|
|
13822
|
-
import { useRef as
|
|
14047
|
+
import { useRef as useRef48, useCallback as useCallback34 } from "react";
|
|
13823
14048
|
function btAction(fn) {
|
|
13824
14049
|
return {
|
|
13825
14050
|
tick(dt) {
|
|
@@ -14032,16 +14257,16 @@ function btFail(child) {
|
|
|
14032
14257
|
};
|
|
14033
14258
|
}
|
|
14034
14259
|
function useBehaviorTree(rootFactory) {
|
|
14035
|
-
const rootRef =
|
|
14260
|
+
const rootRef = useRef48(null);
|
|
14036
14261
|
if (!rootRef.current) rootRef.current = rootFactory();
|
|
14037
|
-
const statusRef =
|
|
14038
|
-
const tick2 =
|
|
14262
|
+
const statusRef = useRef48("failure");
|
|
14263
|
+
const tick2 = useCallback34((dt) => {
|
|
14039
14264
|
if (!rootRef.current) return "failure";
|
|
14040
14265
|
const s2 = rootRef.current.tick(dt);
|
|
14041
14266
|
statusRef.current = s2;
|
|
14042
14267
|
return s2;
|
|
14043
14268
|
}, []);
|
|
14044
|
-
const reset =
|
|
14269
|
+
const reset = useCallback34(() => {
|
|
14045
14270
|
rootRef.current?.reset();
|
|
14046
14271
|
}, []);
|
|
14047
14272
|
return {
|
|
@@ -14162,17 +14387,17 @@ function DialogueBox({ dialogue, onAdvance, onClose, style = {} }) {
|
|
|
14162
14387
|
}
|
|
14163
14388
|
|
|
14164
14389
|
// ../gameplay/src/hooks/useCutscene.ts
|
|
14165
|
-
import { useState as useState31, useCallback as
|
|
14390
|
+
import { useState as useState31, useCallback as useCallback35, useRef as useRef49, useEffect as useEffect82, useContext as useContext77 } from "react";
|
|
14166
14391
|
function useCutscene() {
|
|
14167
14392
|
const engine = useContext77(EngineContext);
|
|
14168
14393
|
const [playing, setPlaying] = useState31(false);
|
|
14169
14394
|
const [stepIndex, setStepIndex] = useState31(0);
|
|
14170
|
-
const stepsRef =
|
|
14171
|
-
const timerRef =
|
|
14172
|
-
const idxRef =
|
|
14173
|
-
const playingRef =
|
|
14174
|
-
const entityRef =
|
|
14175
|
-
const finish =
|
|
14395
|
+
const stepsRef = useRef49([]);
|
|
14396
|
+
const timerRef = useRef49(0);
|
|
14397
|
+
const idxRef = useRef49(0);
|
|
14398
|
+
const playingRef = useRef49(false);
|
|
14399
|
+
const entityRef = useRef49(null);
|
|
14400
|
+
const finish = useCallback35(() => {
|
|
14176
14401
|
playingRef.current = false;
|
|
14177
14402
|
setPlaying(false);
|
|
14178
14403
|
setStepIndex(0);
|
|
@@ -14182,14 +14407,14 @@ function useCutscene() {
|
|
|
14182
14407
|
entityRef.current = null;
|
|
14183
14408
|
}
|
|
14184
14409
|
}, [engine.ecs]);
|
|
14185
|
-
const fireStep =
|
|
14410
|
+
const fireStep = useCallback35((step) => {
|
|
14186
14411
|
if (step.type === "call") step.fn();
|
|
14187
14412
|
if (step.type === "parallel")
|
|
14188
14413
|
step.steps.forEach((s2) => {
|
|
14189
14414
|
if (s2.type === "call") s2.fn();
|
|
14190
14415
|
});
|
|
14191
14416
|
}, []);
|
|
14192
|
-
const play =
|
|
14417
|
+
const play = useCallback35(
|
|
14193
14418
|
(steps) => {
|
|
14194
14419
|
stepsRef.current = steps;
|
|
14195
14420
|
idxRef.current = 0;
|
|
@@ -14246,7 +14471,7 @@ function useCutscene() {
|
|
|
14246
14471
|
},
|
|
14247
14472
|
[engine.ecs, finish, fireStep]
|
|
14248
14473
|
);
|
|
14249
|
-
const skip =
|
|
14474
|
+
const skip = useCallback35(() => {
|
|
14250
14475
|
for (let i = idxRef.current; i < stepsRef.current.length; i++) {
|
|
14251
14476
|
const step = stepsRef.current[i];
|
|
14252
14477
|
if (step.type === "call") step.fn();
|
|
@@ -14257,7 +14482,7 @@ function useCutscene() {
|
|
|
14257
14482
|
}
|
|
14258
14483
|
finish();
|
|
14259
14484
|
}, [finish]);
|
|
14260
|
-
|
|
14485
|
+
useEffect82(() => {
|
|
14261
14486
|
return () => {
|
|
14262
14487
|
if (entityRef.current !== null && engine.ecs.hasEntity(entityRef.current)) {
|
|
14263
14488
|
engine.ecs.destroyEntity(entityRef.current);
|
|
@@ -14268,7 +14493,7 @@ function useCutscene() {
|
|
|
14268
14493
|
}
|
|
14269
14494
|
|
|
14270
14495
|
// ../gameplay/src/hooks/useGameStore.ts
|
|
14271
|
-
import { useSyncExternalStore as useSyncExternalStore2, useCallback as
|
|
14496
|
+
import { useSyncExternalStore as useSyncExternalStore2, useCallback as useCallback36 } from "react";
|
|
14272
14497
|
function createStore(initialState) {
|
|
14273
14498
|
let state = { ...initialState };
|
|
14274
14499
|
const listeners = /* @__PURE__ */ new Set();
|
|
@@ -14294,7 +14519,7 @@ function useGameStore(key, initialState) {
|
|
|
14294
14519
|
}
|
|
14295
14520
|
const store = stores.get(key);
|
|
14296
14521
|
const state = useSyncExternalStore2(store.subscribe, store.getState);
|
|
14297
|
-
const setState =
|
|
14522
|
+
const setState = useCallback36(
|
|
14298
14523
|
(partial) => {
|
|
14299
14524
|
store.setState(partial);
|
|
14300
14525
|
},
|
|
@@ -14304,21 +14529,21 @@ function useGameStore(key, initialState) {
|
|
|
14304
14529
|
}
|
|
14305
14530
|
|
|
14306
14531
|
// ../gameplay/src/hooks/useTween.ts
|
|
14307
|
-
import { useRef as
|
|
14532
|
+
import { useRef as useRef50, useCallback as useCallback37, useEffect as useEffect83 } from "react";
|
|
14308
14533
|
function useTween(opts) {
|
|
14309
|
-
const rafRef =
|
|
14310
|
-
const startTimeRef =
|
|
14311
|
-
const runningRef =
|
|
14312
|
-
const optsRef =
|
|
14534
|
+
const rafRef = useRef50(null);
|
|
14535
|
+
const startTimeRef = useRef50(0);
|
|
14536
|
+
const runningRef = useRef50(false);
|
|
14537
|
+
const optsRef = useRef50(opts);
|
|
14313
14538
|
optsRef.current = opts;
|
|
14314
|
-
const stop =
|
|
14539
|
+
const stop = useCallback37(() => {
|
|
14315
14540
|
if (rafRef.current !== null) {
|
|
14316
14541
|
cancelAnimationFrame(rafRef.current);
|
|
14317
14542
|
rafRef.current = null;
|
|
14318
14543
|
}
|
|
14319
14544
|
runningRef.current = false;
|
|
14320
14545
|
}, []);
|
|
14321
|
-
const start2 =
|
|
14546
|
+
const start2 = useCallback37(() => {
|
|
14322
14547
|
stop();
|
|
14323
14548
|
runningRef.current = true;
|
|
14324
14549
|
startTimeRef.current = performance.now();
|
|
@@ -14340,12 +14565,12 @@ function useTween(opts) {
|
|
|
14340
14565
|
};
|
|
14341
14566
|
rafRef.current = requestAnimationFrame(tick2);
|
|
14342
14567
|
}, [stop]);
|
|
14343
|
-
|
|
14568
|
+
useEffect83(() => {
|
|
14344
14569
|
if (opts.autoStart) {
|
|
14345
14570
|
start2();
|
|
14346
14571
|
}
|
|
14347
14572
|
}, []);
|
|
14348
|
-
|
|
14573
|
+
useEffect83(() => {
|
|
14349
14574
|
return () => {
|
|
14350
14575
|
if (rafRef.current !== null) {
|
|
14351
14576
|
cancelAnimationFrame(rafRef.current);
|
|
@@ -14364,15 +14589,15 @@ function useTween(opts) {
|
|
|
14364
14589
|
}
|
|
14365
14590
|
|
|
14366
14591
|
// ../gameplay/src/hooks/useObjectPool.ts
|
|
14367
|
-
import { useRef as
|
|
14592
|
+
import { useRef as useRef51, useMemo as useMemo18, useEffect as useEffect84 } from "react";
|
|
14368
14593
|
function useObjectPool(factory, reset, initialSize) {
|
|
14369
|
-
const poolRef =
|
|
14370
|
-
const activeRef =
|
|
14371
|
-
const factoryRef =
|
|
14594
|
+
const poolRef = useRef51([]);
|
|
14595
|
+
const activeRef = useRef51(0);
|
|
14596
|
+
const factoryRef = useRef51(factory);
|
|
14372
14597
|
factoryRef.current = factory;
|
|
14373
|
-
const resetRef =
|
|
14598
|
+
const resetRef = useRef51(reset);
|
|
14374
14599
|
resetRef.current = reset;
|
|
14375
|
-
|
|
14600
|
+
useEffect84(() => {
|
|
14376
14601
|
if (initialSize != null && initialSize > 0) {
|
|
14377
14602
|
const pool = poolRef.current;
|
|
14378
14603
|
for (let i = 0; i < initialSize; i++) {
|
|
@@ -14380,7 +14605,7 @@ function useObjectPool(factory, reset, initialSize) {
|
|
|
14380
14605
|
}
|
|
14381
14606
|
}
|
|
14382
14607
|
}, []);
|
|
14383
|
-
return
|
|
14608
|
+
return useMemo18(
|
|
14384
14609
|
() => ({
|
|
14385
14610
|
acquire() {
|
|
14386
14611
|
activeRef.current++;
|
|
@@ -14411,11 +14636,11 @@ function useObjectPool(factory, reset, initialSize) {
|
|
|
14411
14636
|
}
|
|
14412
14637
|
|
|
14413
14638
|
// ../gameplay/src/hooks/useForces.ts
|
|
14414
|
-
import { useContext as useContext78, useMemo as
|
|
14639
|
+
import { useContext as useContext78, useMemo as useMemo19 } from "react";
|
|
14415
14640
|
function useForces() {
|
|
14416
14641
|
const engine = useContext78(EngineContext);
|
|
14417
14642
|
const entityId = useContext78(EntityContext);
|
|
14418
|
-
return
|
|
14643
|
+
return useMemo19(() => {
|
|
14419
14644
|
const getRb = () => engine.ecs.getComponent(entityId, "RigidBody");
|
|
14420
14645
|
const getTransform = () => engine.ecs.getComponent(entityId, "Transform");
|
|
14421
14646
|
const getCenter = () => {
|
|
@@ -14483,11 +14708,11 @@ function useForces() {
|
|
|
14483
14708
|
}
|
|
14484
14709
|
|
|
14485
14710
|
// ../gameplay/src/hooks/useCharacterController.ts
|
|
14486
|
-
import { useContext as useContext79, useMemo as
|
|
14711
|
+
import { useContext as useContext79, useMemo as useMemo20 } from "react";
|
|
14487
14712
|
function useCharacterController(config = {}) {
|
|
14488
14713
|
const engine = useContext79(EngineContext);
|
|
14489
14714
|
const entityId = useContext79(EntityContext);
|
|
14490
|
-
return
|
|
14715
|
+
return useMemo20(() => {
|
|
14491
14716
|
const controller = new CharacterController(config);
|
|
14492
14717
|
return {
|
|
14493
14718
|
move(dx, dy) {
|
|
@@ -14508,7 +14733,7 @@ function createAtlas(names, _columns) {
|
|
|
14508
14733
|
}
|
|
14509
14734
|
|
|
14510
14735
|
// src/components/HUD.tsx
|
|
14511
|
-
import { createContext as createContext3, useContext as useContext80, useMemo as
|
|
14736
|
+
import { createContext as createContext3, useContext as useContext80, useMemo as useMemo21 } from "react";
|
|
14512
14737
|
import { jsx as jsx22, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
14513
14738
|
var HUDContextRef = createContext3(null);
|
|
14514
14739
|
function HUD({
|
|
@@ -14521,7 +14746,7 @@ function HUD({
|
|
|
14521
14746
|
className,
|
|
14522
14747
|
children
|
|
14523
14748
|
}) {
|
|
14524
|
-
const ctx =
|
|
14749
|
+
const ctx = useMemo21(() => ({ padding, safeArea }), [padding, safeArea]);
|
|
14525
14750
|
const rootStyle = {
|
|
14526
14751
|
position: "absolute",
|
|
14527
14752
|
inset: 0,
|
|
@@ -14610,7 +14835,7 @@ function HUDBar({
|
|
|
14610
14835
|
display: "flex",
|
|
14611
14836
|
flexDirection: rtl ? "row-reverse" : "row"
|
|
14612
14837
|
};
|
|
14613
|
-
const
|
|
14838
|
+
const labelStyle2 = {
|
|
14614
14839
|
fontFamily: "system-ui, sans-serif",
|
|
14615
14840
|
fontSize: 11,
|
|
14616
14841
|
letterSpacing: 0.5,
|
|
@@ -14622,7 +14847,7 @@ function HUDBar({
|
|
|
14622
14847
|
marginBottom: 4
|
|
14623
14848
|
};
|
|
14624
14849
|
return /* @__PURE__ */ jsxs11("div", { style: { display: "flex", flexDirection: "column", ...style }, "aria-label": label, children: [
|
|
14625
|
-
(label || showValue) && /* @__PURE__ */ jsxs11("div", { style:
|
|
14850
|
+
(label || showValue) && /* @__PURE__ */ jsxs11("div", { style: labelStyle2, children: [
|
|
14626
14851
|
label && /* @__PURE__ */ jsx22("span", { children: label }),
|
|
14627
14852
|
showValue && /* @__PURE__ */ jsxs11("span", { style: { fontVariantNumeric: "tabular-nums" }, children: [
|
|
14628
14853
|
Math.round(value),
|
|
@@ -14694,7 +14919,7 @@ function definePrefab(name, defaults, render) {
|
|
|
14694
14919
|
}
|
|
14695
14920
|
|
|
14696
14921
|
// src/hooks/useNetworkSync.ts
|
|
14697
|
-
import { useEffect as
|
|
14922
|
+
import { useEffect as useEffect86, useRef as useRef53 } from "react";
|
|
14698
14923
|
|
|
14699
14924
|
// ../../packages/net/src/transport.ts
|
|
14700
14925
|
function isBinaryTransport(t) {
|
|
@@ -15039,7 +15264,7 @@ function syncEntity(config) {
|
|
|
15039
15264
|
}
|
|
15040
15265
|
|
|
15041
15266
|
// ../../packages/net/src/useNetworkInput.ts
|
|
15042
|
-
import { useState as useState32, useEffect as
|
|
15267
|
+
import { useState as useState32, useEffect as useEffect85, useRef as useRef52 } from "react";
|
|
15043
15268
|
var INPUT_MSG_TYPE = "input:state";
|
|
15044
15269
|
function useNetworkInput(config) {
|
|
15045
15270
|
const { room, keys, input, tickRate = 20 } = config;
|
|
@@ -15048,8 +15273,8 @@ function useNetworkInput(config) {
|
|
|
15048
15273
|
() => Object.fromEntries(keys.map((k) => [k, false]))
|
|
15049
15274
|
);
|
|
15050
15275
|
const [remoteInputs] = useState32(() => /* @__PURE__ */ new Map());
|
|
15051
|
-
const localInputRef =
|
|
15052
|
-
|
|
15276
|
+
const localInputRef = useRef52(localInput);
|
|
15277
|
+
useEffect85(() => {
|
|
15053
15278
|
let cleanupDom = null;
|
|
15054
15279
|
if (!input) {
|
|
15055
15280
|
let handleKeyDown2 = function(e) {
|
|
@@ -15263,9 +15488,9 @@ function lerpState(a, b, t) {
|
|
|
15263
15488
|
|
|
15264
15489
|
// src/hooks/useNetworkSync.ts
|
|
15265
15490
|
function useNetworkSync(entityId, components, room, world, owner, opts = {}) {
|
|
15266
|
-
const optsRef =
|
|
15491
|
+
const optsRef = useRef53(opts);
|
|
15267
15492
|
optsRef.current = opts;
|
|
15268
|
-
|
|
15493
|
+
useEffect86(() => {
|
|
15269
15494
|
const sync = syncEntity({
|
|
15270
15495
|
entityId,
|
|
15271
15496
|
components,
|
|
@@ -15280,18 +15505,18 @@ function useNetworkSync(entityId, components, room, world, owner, opts = {}) {
|
|
|
15280
15505
|
}
|
|
15281
15506
|
|
|
15282
15507
|
// src/hooks/useRemotePlayer.ts
|
|
15283
|
-
import { useEffect as
|
|
15508
|
+
import { useEffect as useEffect87, useRef as useRef54, useState as useState33 } from "react";
|
|
15284
15509
|
var PEER_JOIN_MSG = "peer:join";
|
|
15285
15510
|
var PEER_LEAVE_MSG = "peer:leave";
|
|
15286
15511
|
function useRemotePlayer(config) {
|
|
15287
15512
|
const { room, world, createEntity, destroyEntity } = config;
|
|
15288
15513
|
const [players, setPlayers] = useState33(() => /* @__PURE__ */ new Map());
|
|
15289
|
-
const playersRef =
|
|
15290
|
-
const createRef =
|
|
15514
|
+
const playersRef = useRef54(players);
|
|
15515
|
+
const createRef = useRef54(createEntity);
|
|
15291
15516
|
createRef.current = createEntity;
|
|
15292
|
-
const destroyRef =
|
|
15517
|
+
const destroyRef = useRef54(destroyEntity);
|
|
15293
15518
|
destroyRef.current = destroyEntity;
|
|
15294
|
-
|
|
15519
|
+
useEffect87(() => {
|
|
15295
15520
|
function spawnPeer(peerId) {
|
|
15296
15521
|
if (playersRef.current.has(peerId)) return;
|
|
15297
15522
|
const entityId = createRef.current(peerId);
|
|
@@ -15330,12 +15555,558 @@ function useRemotePlayer(config) {
|
|
|
15330
15555
|
}, [room, world]);
|
|
15331
15556
|
return { players };
|
|
15332
15557
|
}
|
|
15558
|
+
|
|
15559
|
+
// ../editor/src/components/SceneHierarchy.tsx
|
|
15560
|
+
import { jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
15561
|
+
var panelStyle = {
|
|
15562
|
+
background: "#0d1520",
|
|
15563
|
+
borderRight: "1px solid #1a2a3a",
|
|
15564
|
+
color: "#c0d0e0",
|
|
15565
|
+
fontFamily: "system-ui, sans-serif",
|
|
15566
|
+
fontSize: 12,
|
|
15567
|
+
display: "flex",
|
|
15568
|
+
flexDirection: "column",
|
|
15569
|
+
overflow: "hidden",
|
|
15570
|
+
userSelect: "none"
|
|
15571
|
+
};
|
|
15572
|
+
var headerStyle = {
|
|
15573
|
+
padding: "6px 10px",
|
|
15574
|
+
fontSize: 10,
|
|
15575
|
+
fontWeight: 700,
|
|
15576
|
+
textTransform: "uppercase",
|
|
15577
|
+
letterSpacing: 1,
|
|
15578
|
+
color: "#4fc3f7",
|
|
15579
|
+
borderBottom: "1px solid #1a2a3a",
|
|
15580
|
+
flexShrink: 0
|
|
15581
|
+
};
|
|
15582
|
+
var listStyle = {
|
|
15583
|
+
flex: 1,
|
|
15584
|
+
overflowY: "auto",
|
|
15585
|
+
padding: "4px 0"
|
|
15586
|
+
};
|
|
15587
|
+
function entityRowStyle(selected) {
|
|
15588
|
+
return {
|
|
15589
|
+
display: "flex",
|
|
15590
|
+
alignItems: "center",
|
|
15591
|
+
gap: 6,
|
|
15592
|
+
padding: "3px 10px",
|
|
15593
|
+
cursor: "pointer",
|
|
15594
|
+
background: selected ? "#1a3050" : "transparent",
|
|
15595
|
+
borderLeft: selected ? "2px solid #4fc3f7" : "2px solid transparent",
|
|
15596
|
+
color: selected ? "#e0f0ff" : "#a0b4c8",
|
|
15597
|
+
transition: "background 80ms"
|
|
15598
|
+
};
|
|
15599
|
+
}
|
|
15600
|
+
var componentBadgeStyle = {
|
|
15601
|
+
fontSize: 9,
|
|
15602
|
+
background: "#1a2a3a",
|
|
15603
|
+
color: "#607080",
|
|
15604
|
+
borderRadius: 3,
|
|
15605
|
+
padding: "1px 4px",
|
|
15606
|
+
maxWidth: 60,
|
|
15607
|
+
overflow: "hidden",
|
|
15608
|
+
textOverflow: "ellipsis",
|
|
15609
|
+
whiteSpace: "nowrap"
|
|
15610
|
+
};
|
|
15611
|
+
function SceneHierarchy({ entities, selectedId, onSelect, width = 220, style }) {
|
|
15612
|
+
return /* @__PURE__ */ jsxs12("div", { style: { ...panelStyle, width, ...style }, children: [
|
|
15613
|
+
/* @__PURE__ */ jsx23("div", { style: headerStyle, children: "Scene Hierarchy" }),
|
|
15614
|
+
/* @__PURE__ */ jsxs12("div", { style: { padding: "4px 10px", borderBottom: "1px solid #1a2a3a", color: "#4a5a6a", fontSize: 10 }, children: [
|
|
15615
|
+
entities.length,
|
|
15616
|
+
" ",
|
|
15617
|
+
entities.length === 1 ? "entity" : "entities"
|
|
15618
|
+
] }),
|
|
15619
|
+
/* @__PURE__ */ jsxs12("div", { style: listStyle, children: [
|
|
15620
|
+
entities.map((e) => /* @__PURE__ */ jsx23(
|
|
15621
|
+
"div",
|
|
15622
|
+
{
|
|
15623
|
+
style: entityRowStyle(e.id === selectedId),
|
|
15624
|
+
onClick: () => onSelect(e.id === selectedId ? null : e.id),
|
|
15625
|
+
children: /* @__PURE__ */ jsxs12("div", { style: { flex: 1, overflow: "hidden" }, children: [
|
|
15626
|
+
/* @__PURE__ */ jsx23("div", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: e.name }),
|
|
15627
|
+
/* @__PURE__ */ jsxs12("div", { style: { display: "flex", gap: 3, marginTop: 2, flexWrap: "wrap" }, children: [
|
|
15628
|
+
e.componentTypes.slice(0, 3).map((t) => /* @__PURE__ */ jsx23("span", { style: componentBadgeStyle, children: t }, t)),
|
|
15629
|
+
e.componentTypes.length > 3 && /* @__PURE__ */ jsxs12("span", { style: componentBadgeStyle, children: [
|
|
15630
|
+
"+",
|
|
15631
|
+
e.componentTypes.length - 3
|
|
15632
|
+
] })
|
|
15633
|
+
] })
|
|
15634
|
+
] })
|
|
15635
|
+
},
|
|
15636
|
+
e.id
|
|
15637
|
+
)),
|
|
15638
|
+
entities.length === 0 && /* @__PURE__ */ jsx23("div", { style: { padding: "10px", color: "#3a5060", fontSize: 11, textAlign: "center" }, children: "No entities" })
|
|
15639
|
+
] })
|
|
15640
|
+
] });
|
|
15641
|
+
}
|
|
15642
|
+
|
|
15643
|
+
// ../editor/src/components/PropertyField.tsx
|
|
15644
|
+
import { jsx as jsx24, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
15645
|
+
var fieldRow = {
|
|
15646
|
+
display: "flex",
|
|
15647
|
+
alignItems: "center",
|
|
15648
|
+
gap: 6,
|
|
15649
|
+
marginBottom: 4,
|
|
15650
|
+
minHeight: 24
|
|
15651
|
+
};
|
|
15652
|
+
var labelStyle = {
|
|
15653
|
+
flex: "0 0 90px",
|
|
15654
|
+
fontSize: 11,
|
|
15655
|
+
color: "#8899aa",
|
|
15656
|
+
overflow: "hidden",
|
|
15657
|
+
textOverflow: "ellipsis",
|
|
15658
|
+
whiteSpace: "nowrap",
|
|
15659
|
+
fontFamily: "system-ui, sans-serif",
|
|
15660
|
+
textTransform: "uppercase",
|
|
15661
|
+
letterSpacing: 0.5
|
|
15662
|
+
};
|
|
15663
|
+
var inputBase = {
|
|
15664
|
+
flex: 1,
|
|
15665
|
+
background: "#1a2030",
|
|
15666
|
+
border: "1px solid #2a3a50",
|
|
15667
|
+
borderRadius: 3,
|
|
15668
|
+
color: "#d0e0f0",
|
|
15669
|
+
padding: "2px 6px",
|
|
15670
|
+
fontSize: 11,
|
|
15671
|
+
fontFamily: "monospace",
|
|
15672
|
+
outline: "none",
|
|
15673
|
+
minWidth: 0
|
|
15674
|
+
};
|
|
15675
|
+
function NumberField({ label, value, onChange, step = 1 }) {
|
|
15676
|
+
return /* @__PURE__ */ jsxs13("div", { style: fieldRow, children: [
|
|
15677
|
+
/* @__PURE__ */ jsx24("span", { style: labelStyle, title: label, children: label }),
|
|
15678
|
+
/* @__PURE__ */ jsx24(
|
|
15679
|
+
"input",
|
|
15680
|
+
{
|
|
15681
|
+
type: "number",
|
|
15682
|
+
style: inputBase,
|
|
15683
|
+
value: isNaN(value) ? "" : value,
|
|
15684
|
+
step,
|
|
15685
|
+
onChange: (e) => {
|
|
15686
|
+
const v = parseFloat(e.target.value);
|
|
15687
|
+
if (!isNaN(v)) onChange(v);
|
|
15688
|
+
}
|
|
15689
|
+
}
|
|
15690
|
+
)
|
|
15691
|
+
] });
|
|
15692
|
+
}
|
|
15693
|
+
function TextField({ label, value, onChange }) {
|
|
15694
|
+
return /* @__PURE__ */ jsxs13("div", { style: fieldRow, children: [
|
|
15695
|
+
/* @__PURE__ */ jsx24("span", { style: labelStyle, title: label, children: label }),
|
|
15696
|
+
/* @__PURE__ */ jsx24("input", { type: "text", style: inputBase, value, onChange: (e) => onChange(e.target.value) })
|
|
15697
|
+
] });
|
|
15698
|
+
}
|
|
15699
|
+
function BoolField({ label, value, onChange }) {
|
|
15700
|
+
return /* @__PURE__ */ jsxs13("div", { style: fieldRow, children: [
|
|
15701
|
+
/* @__PURE__ */ jsx24("span", { style: labelStyle, title: label, children: label }),
|
|
15702
|
+
/* @__PURE__ */ jsx24(
|
|
15703
|
+
"input",
|
|
15704
|
+
{
|
|
15705
|
+
type: "checkbox",
|
|
15706
|
+
checked: value,
|
|
15707
|
+
style: { accentColor: "#4fc3f7", cursor: "pointer" },
|
|
15708
|
+
onChange: (e) => onChange(e.target.checked)
|
|
15709
|
+
}
|
|
15710
|
+
)
|
|
15711
|
+
] });
|
|
15712
|
+
}
|
|
15713
|
+
function ColorField({ label, value, onChange }) {
|
|
15714
|
+
return /* @__PURE__ */ jsxs13("div", { style: fieldRow, children: [
|
|
15715
|
+
/* @__PURE__ */ jsx24("span", { style: labelStyle, title: label, children: label }),
|
|
15716
|
+
/* @__PURE__ */ jsxs13("div", { style: { display: "flex", gap: 4, flex: 1 }, children: [
|
|
15717
|
+
/* @__PURE__ */ jsx24(
|
|
15718
|
+
"input",
|
|
15719
|
+
{
|
|
15720
|
+
type: "color",
|
|
15721
|
+
value: value.startsWith("#") ? value.slice(0, 7) : "#ffffff",
|
|
15722
|
+
style: { width: 28, height: 22, padding: 1, border: "1px solid #2a3a50", borderRadius: 3, cursor: "pointer" },
|
|
15723
|
+
onChange: (e) => onChange(e.target.value)
|
|
15724
|
+
}
|
|
15725
|
+
),
|
|
15726
|
+
/* @__PURE__ */ jsx24("input", { type: "text", style: { ...inputBase, flex: 1 }, value, onChange: (e) => onChange(e.target.value) })
|
|
15727
|
+
] })
|
|
15728
|
+
] });
|
|
15729
|
+
}
|
|
15730
|
+
function Vec2Field({ label, x, y, onChangeX, onChangeY, step = 1 }) {
|
|
15731
|
+
return /* @__PURE__ */ jsxs13("div", { style: fieldRow, children: [
|
|
15732
|
+
/* @__PURE__ */ jsx24("span", { style: labelStyle, title: label, children: label }),
|
|
15733
|
+
/* @__PURE__ */ jsxs13("div", { style: { display: "flex", gap: 4, flex: 1 }, children: [
|
|
15734
|
+
/* @__PURE__ */ jsx24(
|
|
15735
|
+
"input",
|
|
15736
|
+
{
|
|
15737
|
+
type: "number",
|
|
15738
|
+
style: { ...inputBase, flex: 1 },
|
|
15739
|
+
value: isNaN(x) ? "" : x,
|
|
15740
|
+
step,
|
|
15741
|
+
onChange: (e) => {
|
|
15742
|
+
const v = parseFloat(e.target.value);
|
|
15743
|
+
if (!isNaN(v)) onChangeX(v);
|
|
15744
|
+
}
|
|
15745
|
+
}
|
|
15746
|
+
),
|
|
15747
|
+
/* @__PURE__ */ jsx24(
|
|
15748
|
+
"input",
|
|
15749
|
+
{
|
|
15750
|
+
type: "number",
|
|
15751
|
+
style: { ...inputBase, flex: 1 },
|
|
15752
|
+
value: isNaN(y) ? "" : y,
|
|
15753
|
+
step,
|
|
15754
|
+
onChange: (e) => {
|
|
15755
|
+
const v = parseFloat(e.target.value);
|
|
15756
|
+
if (!isNaN(v)) onChangeY(v);
|
|
15757
|
+
}
|
|
15758
|
+
}
|
|
15759
|
+
)
|
|
15760
|
+
] })
|
|
15761
|
+
] });
|
|
15762
|
+
}
|
|
15763
|
+
|
|
15764
|
+
// ../editor/src/components/EntityInspector.tsx
|
|
15765
|
+
import { Fragment as Fragment10, jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
15766
|
+
var panelStyle2 = {
|
|
15767
|
+
background: "#0d1520",
|
|
15768
|
+
borderLeft: "1px solid #1a2a3a",
|
|
15769
|
+
color: "#c0d0e0",
|
|
15770
|
+
fontFamily: "system-ui, sans-serif",
|
|
15771
|
+
fontSize: 12,
|
|
15772
|
+
display: "flex",
|
|
15773
|
+
flexDirection: "column",
|
|
15774
|
+
overflow: "hidden",
|
|
15775
|
+
userSelect: "none"
|
|
15776
|
+
};
|
|
15777
|
+
var headerStyle2 = {
|
|
15778
|
+
padding: "6px 10px",
|
|
15779
|
+
fontSize: 10,
|
|
15780
|
+
fontWeight: 700,
|
|
15781
|
+
textTransform: "uppercase",
|
|
15782
|
+
letterSpacing: 1,
|
|
15783
|
+
color: "#4fc3f7",
|
|
15784
|
+
borderBottom: "1px solid #1a2a3a",
|
|
15785
|
+
flexShrink: 0
|
|
15786
|
+
};
|
|
15787
|
+
var scrollStyle = {
|
|
15788
|
+
flex: 1,
|
|
15789
|
+
overflowY: "auto",
|
|
15790
|
+
padding: "6px 0"
|
|
15791
|
+
};
|
|
15792
|
+
var componentSectionStyle = {
|
|
15793
|
+
marginBottom: 2,
|
|
15794
|
+
borderBottom: "1px solid #131d2a"
|
|
15795
|
+
};
|
|
15796
|
+
var componentHeaderStyle = {
|
|
15797
|
+
display: "flex",
|
|
15798
|
+
alignItems: "center",
|
|
15799
|
+
padding: "4px 10px",
|
|
15800
|
+
fontSize: 10,
|
|
15801
|
+
fontWeight: 700,
|
|
15802
|
+
textTransform: "uppercase",
|
|
15803
|
+
letterSpacing: 0.8,
|
|
15804
|
+
color: "#80a8c0",
|
|
15805
|
+
cursor: "default",
|
|
15806
|
+
background: "#0f1a28"
|
|
15807
|
+
};
|
|
15808
|
+
var fieldsStyle = {
|
|
15809
|
+
padding: "4px 10px 6px"
|
|
15810
|
+
};
|
|
15811
|
+
function isColorKey(key) {
|
|
15812
|
+
const lower = key.toLowerCase();
|
|
15813
|
+
return lower === "color" || lower === "background" || lower === "fill" || lower === "stroke" || lower.includes("color");
|
|
15814
|
+
}
|
|
15815
|
+
function ComponentSection({ comp }) {
|
|
15816
|
+
const compRecord = comp;
|
|
15817
|
+
const entries = Object.entries(comp).filter(([k]) => k !== "type");
|
|
15818
|
+
const rendered = /* @__PURE__ */ new Set();
|
|
15819
|
+
return /* @__PURE__ */ jsxs14("div", { style: componentSectionStyle, children: [
|
|
15820
|
+
/* @__PURE__ */ jsx25("div", { style: componentHeaderStyle, children: comp.type }),
|
|
15821
|
+
/* @__PURE__ */ jsxs14("div", { style: fieldsStyle, children: [
|
|
15822
|
+
entries.map(([key, val]) => {
|
|
15823
|
+
if (rendered.has(key)) return null;
|
|
15824
|
+
if (key === "x" && typeof val === "number" && typeof compRecord["y"] === "number") {
|
|
15825
|
+
rendered.add("x");
|
|
15826
|
+
rendered.add("y");
|
|
15827
|
+
return /* @__PURE__ */ jsx25(
|
|
15828
|
+
Vec2Field,
|
|
15829
|
+
{
|
|
15830
|
+
label: "pos",
|
|
15831
|
+
x: val,
|
|
15832
|
+
y: compRecord["y"],
|
|
15833
|
+
step: 0.5,
|
|
15834
|
+
onChangeX: (v) => {
|
|
15835
|
+
compRecord["x"] = v;
|
|
15836
|
+
},
|
|
15837
|
+
onChangeY: (v) => {
|
|
15838
|
+
compRecord["y"] = v;
|
|
15839
|
+
}
|
|
15840
|
+
},
|
|
15841
|
+
"xy"
|
|
15842
|
+
);
|
|
15843
|
+
}
|
|
15844
|
+
if (key === "followOffsetX" && typeof val === "number") {
|
|
15845
|
+
const oy = compRecord["followOffsetY"];
|
|
15846
|
+
if (typeof oy === "number") {
|
|
15847
|
+
rendered.add("followOffsetX");
|
|
15848
|
+
rendered.add("followOffsetY");
|
|
15849
|
+
return /* @__PURE__ */ jsx25(
|
|
15850
|
+
Vec2Field,
|
|
15851
|
+
{
|
|
15852
|
+
label: "offset",
|
|
15853
|
+
x: val,
|
|
15854
|
+
y: oy,
|
|
15855
|
+
step: 1,
|
|
15856
|
+
onChangeX: (v) => {
|
|
15857
|
+
compRecord["followOffsetX"] = v;
|
|
15858
|
+
},
|
|
15859
|
+
onChangeY: (v) => {
|
|
15860
|
+
compRecord["followOffsetY"] = v;
|
|
15861
|
+
}
|
|
15862
|
+
},
|
|
15863
|
+
"followOffset"
|
|
15864
|
+
);
|
|
15865
|
+
}
|
|
15866
|
+
}
|
|
15867
|
+
if (typeof val === "number") {
|
|
15868
|
+
rendered.add(key);
|
|
15869
|
+
return /* @__PURE__ */ jsx25(
|
|
15870
|
+
NumberField,
|
|
15871
|
+
{
|
|
15872
|
+
label: key,
|
|
15873
|
+
value: val,
|
|
15874
|
+
step: Math.abs(val) < 2 ? 0.01 : 1,
|
|
15875
|
+
onChange: (v) => {
|
|
15876
|
+
compRecord[key] = v;
|
|
15877
|
+
}
|
|
15878
|
+
},
|
|
15879
|
+
key
|
|
15880
|
+
);
|
|
15881
|
+
}
|
|
15882
|
+
if (typeof val === "string" && isColorKey(key)) {
|
|
15883
|
+
rendered.add(key);
|
|
15884
|
+
return /* @__PURE__ */ jsx25(
|
|
15885
|
+
ColorField,
|
|
15886
|
+
{
|
|
15887
|
+
label: key,
|
|
15888
|
+
value: val,
|
|
15889
|
+
onChange: (v) => {
|
|
15890
|
+
compRecord[key] = v;
|
|
15891
|
+
}
|
|
15892
|
+
},
|
|
15893
|
+
key
|
|
15894
|
+
);
|
|
15895
|
+
}
|
|
15896
|
+
if (typeof val === "string") {
|
|
15897
|
+
rendered.add(key);
|
|
15898
|
+
return /* @__PURE__ */ jsx25(
|
|
15899
|
+
TextField,
|
|
15900
|
+
{
|
|
15901
|
+
label: key,
|
|
15902
|
+
value: val,
|
|
15903
|
+
onChange: (v) => {
|
|
15904
|
+
compRecord[key] = v;
|
|
15905
|
+
}
|
|
15906
|
+
},
|
|
15907
|
+
key
|
|
15908
|
+
);
|
|
15909
|
+
}
|
|
15910
|
+
if (typeof val === "boolean") {
|
|
15911
|
+
rendered.add(key);
|
|
15912
|
+
return /* @__PURE__ */ jsx25(
|
|
15913
|
+
BoolField,
|
|
15914
|
+
{
|
|
15915
|
+
label: key,
|
|
15916
|
+
value: val,
|
|
15917
|
+
onChange: (v) => {
|
|
15918
|
+
compRecord[key] = v;
|
|
15919
|
+
}
|
|
15920
|
+
},
|
|
15921
|
+
key
|
|
15922
|
+
);
|
|
15923
|
+
}
|
|
15924
|
+
if (val !== null && val !== void 0 && typeof val !== "function") {
|
|
15925
|
+
rendered.add(key);
|
|
15926
|
+
const preview = typeof val === "object" ? JSON.stringify(val).slice(0, 60) : String(val);
|
|
15927
|
+
return /* @__PURE__ */ jsxs14(
|
|
15928
|
+
"div",
|
|
15929
|
+
{
|
|
15930
|
+
style: {
|
|
15931
|
+
display: "flex",
|
|
15932
|
+
gap: 6,
|
|
15933
|
+
marginBottom: 4,
|
|
15934
|
+
fontSize: 11,
|
|
15935
|
+
alignItems: "flex-start"
|
|
15936
|
+
},
|
|
15937
|
+
children: [
|
|
15938
|
+
/* @__PURE__ */ jsx25(
|
|
15939
|
+
"span",
|
|
15940
|
+
{
|
|
15941
|
+
style: {
|
|
15942
|
+
flex: "0 0 90px",
|
|
15943
|
+
color: "#6a7a8a",
|
|
15944
|
+
textTransform: "uppercase",
|
|
15945
|
+
fontSize: 10,
|
|
15946
|
+
letterSpacing: 0.5,
|
|
15947
|
+
paddingTop: 2
|
|
15948
|
+
},
|
|
15949
|
+
children: key
|
|
15950
|
+
}
|
|
15951
|
+
),
|
|
15952
|
+
/* @__PURE__ */ jsx25(
|
|
15953
|
+
"span",
|
|
15954
|
+
{
|
|
15955
|
+
style: { flex: 1, color: "#506070", fontFamily: "monospace", wordBreak: "break-all", fontSize: 10 },
|
|
15956
|
+
children: preview
|
|
15957
|
+
}
|
|
15958
|
+
)
|
|
15959
|
+
]
|
|
15960
|
+
},
|
|
15961
|
+
key
|
|
15962
|
+
);
|
|
15963
|
+
}
|
|
15964
|
+
return null;
|
|
15965
|
+
}),
|
|
15966
|
+
entries.length === 0 && /* @__PURE__ */ jsx25("div", { style: { color: "#3a5060", fontSize: 10 }, children: "No fields" })
|
|
15967
|
+
] })
|
|
15968
|
+
] });
|
|
15969
|
+
}
|
|
15970
|
+
function EntityInspector({ entity, components, width = 260, style }) {
|
|
15971
|
+
return /* @__PURE__ */ jsxs14("div", { style: { ...panelStyle2, width, ...style }, children: [
|
|
15972
|
+
/* @__PURE__ */ jsx25("div", { style: headerStyle2, children: "Inspector" }),
|
|
15973
|
+
entity ? /* @__PURE__ */ jsxs14(Fragment10, { children: [
|
|
15974
|
+
/* @__PURE__ */ jsxs14(
|
|
15975
|
+
"div",
|
|
15976
|
+
{
|
|
15977
|
+
style: {
|
|
15978
|
+
padding: "6px 10px",
|
|
15979
|
+
borderBottom: "1px solid #1a2a3a",
|
|
15980
|
+
color: "#d0e0f0",
|
|
15981
|
+
fontSize: 12,
|
|
15982
|
+
fontWeight: 600
|
|
15983
|
+
},
|
|
15984
|
+
children: [
|
|
15985
|
+
entity.name,
|
|
15986
|
+
/* @__PURE__ */ jsxs14("span", { style: { color: "#4a6070", fontSize: 10, marginLeft: 6 }, children: [
|
|
15987
|
+
"#",
|
|
15988
|
+
entity.id
|
|
15989
|
+
] })
|
|
15990
|
+
]
|
|
15991
|
+
}
|
|
15992
|
+
),
|
|
15993
|
+
/* @__PURE__ */ jsxs14("div", { style: scrollStyle, children: [
|
|
15994
|
+
components.map((comp) => /* @__PURE__ */ jsx25(ComponentSection, { comp }, comp.type)),
|
|
15995
|
+
components.length === 0 && /* @__PURE__ */ jsx25("div", { style: { padding: "10px", color: "#3a5060", fontSize: 11, textAlign: "center" }, children: "No components" })
|
|
15996
|
+
] })
|
|
15997
|
+
] }) : /* @__PURE__ */ jsx25(
|
|
15998
|
+
"div",
|
|
15999
|
+
{
|
|
16000
|
+
style: {
|
|
16001
|
+
flex: 1,
|
|
16002
|
+
display: "flex",
|
|
16003
|
+
alignItems: "center",
|
|
16004
|
+
justifyContent: "center",
|
|
16005
|
+
color: "#2a4050",
|
|
16006
|
+
fontSize: 11
|
|
16007
|
+
},
|
|
16008
|
+
children: "Select an entity"
|
|
16009
|
+
}
|
|
16010
|
+
)
|
|
16011
|
+
] });
|
|
16012
|
+
}
|
|
16013
|
+
|
|
16014
|
+
// ../editor/src/hooks/useEditorState.ts
|
|
16015
|
+
import { useState as useState34, useCallback as useCallback38, useContext as useContext81, useEffect as useEffect88, useRef as useRef55 } from "react";
|
|
16016
|
+
function buildEntityInfo(engine) {
|
|
16017
|
+
const nameMap = /* @__PURE__ */ new Map();
|
|
16018
|
+
engine.entityIds.forEach((eid, name) => nameMap.set(eid, name));
|
|
16019
|
+
const ids = engine.ecs.getAllEntityIds();
|
|
16020
|
+
return ids.map((id) => {
|
|
16021
|
+
const comps = engine.ecs.getEntityComponents(id);
|
|
16022
|
+
return {
|
|
16023
|
+
id,
|
|
16024
|
+
name: nameMap.get(id) ?? `Entity #${id}`,
|
|
16025
|
+
componentTypes: comps.map((c) => c.type)
|
|
16026
|
+
};
|
|
16027
|
+
});
|
|
16028
|
+
}
|
|
16029
|
+
function useEditorState(refreshHz = 4) {
|
|
16030
|
+
const engine = useContext81(EngineContext);
|
|
16031
|
+
const [entities, setEntities] = useState34([]);
|
|
16032
|
+
const [selectedId, setSelectedId] = useState34(null);
|
|
16033
|
+
const intervalRef = useRef55(null);
|
|
16034
|
+
const refresh = useCallback38(() => {
|
|
16035
|
+
setEntities(buildEntityInfo(engine));
|
|
16036
|
+
}, [engine]);
|
|
16037
|
+
useEffect88(() => {
|
|
16038
|
+
refresh();
|
|
16039
|
+
intervalRef.current = setInterval(refresh, 1e3 / refreshHz);
|
|
16040
|
+
return () => {
|
|
16041
|
+
if (intervalRef.current !== null) clearInterval(intervalRef.current);
|
|
16042
|
+
};
|
|
16043
|
+
}, [refresh, refreshHz]);
|
|
16044
|
+
const select = useCallback38((id) => {
|
|
16045
|
+
setSelectedId(id);
|
|
16046
|
+
}, []);
|
|
16047
|
+
const selectedComponents = selectedId !== null ? engine.ecs.getEntityComponents(selectedId) : [];
|
|
16048
|
+
return { entities, selectedId, selectedComponents, select, refresh };
|
|
16049
|
+
}
|
|
16050
|
+
|
|
16051
|
+
// ../editor/src/components/EditorShell.tsx
|
|
16052
|
+
import { Fragment as Fragment11, jsx as jsx26, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
16053
|
+
function EditorShell({
|
|
16054
|
+
children,
|
|
16055
|
+
active = true,
|
|
16056
|
+
hierarchyWidth = 220,
|
|
16057
|
+
inspectorWidth = 260,
|
|
16058
|
+
style
|
|
16059
|
+
}) {
|
|
16060
|
+
const state = useEditorState();
|
|
16061
|
+
const selectedEntity = state.entities.find((e) => e.id === state.selectedId) ?? null;
|
|
16062
|
+
if (!active) {
|
|
16063
|
+
return /* @__PURE__ */ jsx26(Fragment11, { children });
|
|
16064
|
+
}
|
|
16065
|
+
const shellStyle = {
|
|
16066
|
+
position: "absolute",
|
|
16067
|
+
inset: 0,
|
|
16068
|
+
display: "flex",
|
|
16069
|
+
flexDirection: "row",
|
|
16070
|
+
pointerEvents: "none",
|
|
16071
|
+
zIndex: 200,
|
|
16072
|
+
...style
|
|
16073
|
+
};
|
|
16074
|
+
const sideStyle = {
|
|
16075
|
+
pointerEvents: "auto",
|
|
16076
|
+
flexShrink: 0,
|
|
16077
|
+
height: "100%",
|
|
16078
|
+
overflow: "hidden"
|
|
16079
|
+
};
|
|
16080
|
+
return /* @__PURE__ */ jsxs15("div", { style: shellStyle, children: [
|
|
16081
|
+
/* @__PURE__ */ jsx26("div", { style: sideStyle, children: /* @__PURE__ */ jsx26(
|
|
16082
|
+
SceneHierarchy,
|
|
16083
|
+
{
|
|
16084
|
+
entities: state.entities,
|
|
16085
|
+
selectedId: state.selectedId,
|
|
16086
|
+
onSelect: state.select,
|
|
16087
|
+
width: hierarchyWidth,
|
|
16088
|
+
style: { height: "100%" }
|
|
16089
|
+
}
|
|
16090
|
+
) }),
|
|
16091
|
+
/* @__PURE__ */ jsx26("div", { style: { flex: 1, pointerEvents: "none" }, children }),
|
|
16092
|
+
/* @__PURE__ */ jsx26("div", { style: sideStyle, children: /* @__PURE__ */ jsx26(
|
|
16093
|
+
EntityInspector,
|
|
16094
|
+
{
|
|
16095
|
+
entity: selectedEntity,
|
|
16096
|
+
components: state.selectedComponents,
|
|
16097
|
+
width: inspectorWidth,
|
|
16098
|
+
style: { height: "100%" }
|
|
16099
|
+
}
|
|
16100
|
+
) })
|
|
16101
|
+
] });
|
|
16102
|
+
}
|
|
15333
16103
|
export {
|
|
15334
16104
|
A11yNode,
|
|
15335
16105
|
AnimatedSprite,
|
|
15336
16106
|
Animation,
|
|
15337
16107
|
Animator,
|
|
15338
16108
|
AssetLoader,
|
|
16109
|
+
BoolField,
|
|
15339
16110
|
BoxCollider,
|
|
15340
16111
|
COLLISION_DYNAMIC_DYNAMIC,
|
|
15341
16112
|
COLLISION_DYNAMIC_KINEMATIC,
|
|
@@ -15351,6 +16122,7 @@ export {
|
|
|
15351
16122
|
CircleCollider,
|
|
15352
16123
|
ClientPrediction,
|
|
15353
16124
|
CollisionPipeline,
|
|
16125
|
+
ColorField,
|
|
15354
16126
|
ComboDetector,
|
|
15355
16127
|
CompoundCollider,
|
|
15356
16128
|
ConvexCollider,
|
|
@@ -15359,7 +16131,9 @@ export {
|
|
|
15359
16131
|
DialogueBox,
|
|
15360
16132
|
Ease,
|
|
15361
16133
|
EditableText,
|
|
16134
|
+
EditorShell,
|
|
15362
16135
|
Entity,
|
|
16136
|
+
EntityInspector,
|
|
15363
16137
|
FocusRing,
|
|
15364
16138
|
Game,
|
|
15365
16139
|
Gradient,
|
|
@@ -15377,6 +16151,7 @@ export {
|
|
|
15377
16151
|
Mask,
|
|
15378
16152
|
MovingPlatform,
|
|
15379
16153
|
NineSlice,
|
|
16154
|
+
NumberField,
|
|
15380
16155
|
PARTICLE_PRESETS,
|
|
15381
16156
|
ParallaxLayer,
|
|
15382
16157
|
ParticleEmitter,
|
|
@@ -15384,6 +16159,7 @@ export {
|
|
|
15384
16159
|
RenderSystem,
|
|
15385
16160
|
RigidBody,
|
|
15386
16161
|
Room,
|
|
16162
|
+
SceneHierarchy,
|
|
15387
16163
|
SceneTransitionOverlay,
|
|
15388
16164
|
ScreenFlash,
|
|
15389
16165
|
Script,
|
|
@@ -15394,6 +16170,7 @@ export {
|
|
|
15394
16170
|
SquashStretch,
|
|
15395
16171
|
Stage,
|
|
15396
16172
|
Text,
|
|
16173
|
+
TextField,
|
|
15397
16174
|
TextureFilter,
|
|
15398
16175
|
Tilemap,
|
|
15399
16176
|
Trail,
|
|
@@ -15401,6 +16178,7 @@ export {
|
|
|
15401
16178
|
TransformHandles,
|
|
15402
16179
|
TriMeshCollider,
|
|
15403
16180
|
TriangleCollider,
|
|
16181
|
+
Vec2Field,
|
|
15404
16182
|
VectorPath,
|
|
15405
16183
|
VirtualCamera,
|
|
15406
16184
|
VirtualJoystick,
|
|
@@ -15578,6 +16356,8 @@ export {
|
|
|
15578
16356
|
useDraggable,
|
|
15579
16357
|
useDropThrough,
|
|
15580
16358
|
useDroppable,
|
|
16359
|
+
useDynamicCanvas,
|
|
16360
|
+
useEditorState,
|
|
15581
16361
|
useEntity,
|
|
15582
16362
|
useEvent,
|
|
15583
16363
|
useEvents,
|
|
@@ -15596,6 +16376,7 @@ export {
|
|
|
15596
16376
|
useHitstop,
|
|
15597
16377
|
useHoverable,
|
|
15598
16378
|
useIDBSave,
|
|
16379
|
+
useIdleFrameSkip,
|
|
15599
16380
|
useInput,
|
|
15600
16381
|
useInputBuffer,
|
|
15601
16382
|
useInputContext,
|