cubeforge 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advanced.js +1 -1
- package/dist/{chunk-OT6I5RYW.js → chunk-UMHYQ4EP.js} +101 -31
- package/dist/index.d.ts +184 -2
- package/dist/index.js +512 -134
- package/package.json +1 -1
package/dist/advanced.js
CHANGED
|
@@ -5261,6 +5261,31 @@ var PhysicsSystem = class {
|
|
|
5261
5261
|
bvhCache = /* @__PURE__ */ new Map();
|
|
5262
5262
|
// Physics hooks for filtering and modifying contacts
|
|
5263
5263
|
hooks = {};
|
|
5264
|
+
// ── Scratch containers — reused every frame to avoid GC pressure ──────────
|
|
5265
|
+
//
|
|
5266
|
+
// Previously these were allocated fresh inside update() every substep,
|
|
5267
|
+
// producing ~20 Map/Set allocations per frame. Now they live as instance
|
|
5268
|
+
// fields and are cleared at the start of each use. Never escape the class.
|
|
5269
|
+
//
|
|
5270
|
+
// The _current*Pairs fields are double-buffered with their active*Pairs
|
|
5271
|
+
// counterparts: at the end of each substep, the filled "current" is swapped
|
|
5272
|
+
// with "active", and next substep clears the new "current" (which was the
|
|
5273
|
+
// previous "active"). Same enter/stay/exit event semantics, zero allocation.
|
|
5274
|
+
_staticDelta = /* @__PURE__ */ new Map();
|
|
5275
|
+
_preStepPos = /* @__PURE__ */ new Map();
|
|
5276
|
+
_spatialGrid = /* @__PURE__ */ new Map();
|
|
5277
|
+
_jointExcludedPairs = /* @__PURE__ */ new Set();
|
|
5278
|
+
_solverBodies = /* @__PURE__ */ new Map();
|
|
5279
|
+
_triggerNormals = /* @__PURE__ */ new Map();
|
|
5280
|
+
_circleNormals = /* @__PURE__ */ new Map();
|
|
5281
|
+
/** Shared scratch for per-body "checked" neighbor dedup; cleared per iteration. */
|
|
5282
|
+
_checkedScratch = /* @__PURE__ */ new Set();
|
|
5283
|
+
_currentCollisionPairs = /* @__PURE__ */ new Map();
|
|
5284
|
+
_currentTriggerPairs = /* @__PURE__ */ new Map();
|
|
5285
|
+
_currentCirclePairs = /* @__PURE__ */ new Map();
|
|
5286
|
+
_currentCompoundPairs = /* @__PURE__ */ new Map();
|
|
5287
|
+
_currentCapsulePairs = /* @__PURE__ */ new Map();
|
|
5288
|
+
_currentPolygonPairs = /* @__PURE__ */ new Map();
|
|
5264
5289
|
/** Set physics hooks for contact filtering and modification. */
|
|
5265
5290
|
setHooks(hooks) {
|
|
5266
5291
|
this.hooks = hooks;
|
|
@@ -5421,7 +5446,8 @@ var PhysicsSystem = class {
|
|
|
5421
5446
|
}
|
|
5422
5447
|
const nonDynamic = [...staticBox, ...kinematicBox];
|
|
5423
5448
|
this.pruneDeadPairs(world);
|
|
5424
|
-
const staticDelta =
|
|
5449
|
+
const staticDelta = this._staticDelta;
|
|
5450
|
+
staticDelta.clear();
|
|
5425
5451
|
for (const sid of nonDynamic) {
|
|
5426
5452
|
const st = world.getComponent(sid, "Transform");
|
|
5427
5453
|
const prev = this.staticPrevPos.get(sid);
|
|
@@ -5551,12 +5577,14 @@ var PhysicsSystem = class {
|
|
|
5551
5577
|
}
|
|
5552
5578
|
if (rb.dropThrough > 0) rb.dropThrough--;
|
|
5553
5579
|
}
|
|
5554
|
-
const preStepPos =
|
|
5580
|
+
const preStepPos = this._preStepPos;
|
|
5581
|
+
preStepPos.clear();
|
|
5555
5582
|
for (const id of dynamicBox) {
|
|
5556
5583
|
const t = world.getComponent(id, "Transform");
|
|
5557
5584
|
preStepPos.set(id, { x: t.x, y: t.y });
|
|
5558
5585
|
}
|
|
5559
|
-
const spatialGrid =
|
|
5586
|
+
const spatialGrid = this._spatialGrid;
|
|
5587
|
+
spatialGrid.clear();
|
|
5560
5588
|
for (const sid of nonDynamic) {
|
|
5561
5589
|
const st = world.getComponent(sid, "Transform");
|
|
5562
5590
|
const sc = world.getComponent(sid, "BoxCollider");
|
|
@@ -5571,7 +5599,8 @@ var PhysicsSystem = class {
|
|
|
5571
5599
|
bucket.push(sid);
|
|
5572
5600
|
}
|
|
5573
5601
|
}
|
|
5574
|
-
const jointExcludedPairs =
|
|
5602
|
+
const jointExcludedPairs = this._jointExcludedPairs;
|
|
5603
|
+
jointExcludedPairs.clear();
|
|
5575
5604
|
for (const jid of world.query("Joint")) {
|
|
5576
5605
|
const j = world.getComponent(jid, "Joint");
|
|
5577
5606
|
if (!j.enabled || j.broken) continue;
|
|
@@ -5581,7 +5610,8 @@ var PhysicsSystem = class {
|
|
|
5581
5610
|
}
|
|
5582
5611
|
}
|
|
5583
5612
|
const manifolds = [];
|
|
5584
|
-
const currentCollisionPairs =
|
|
5613
|
+
const currentCollisionPairs = this._currentCollisionPairs;
|
|
5614
|
+
currentCollisionPairs.clear();
|
|
5585
5615
|
for (const id of dynamicBox) {
|
|
5586
5616
|
const rb = world.getComponent(id, "RigidBody");
|
|
5587
5617
|
if (rb.sleeping) continue;
|
|
@@ -5590,7 +5620,8 @@ var PhysicsSystem = class {
|
|
|
5590
5620
|
if (!col.enabled || col.isTrigger) continue;
|
|
5591
5621
|
const dynAABB = getAABB2(transform, col);
|
|
5592
5622
|
const candidateCells = this.getCells(dynAABB.cx, dynAABB.cy, dynAABB.hw, dynAABB.hh);
|
|
5593
|
-
const checked =
|
|
5623
|
+
const checked = this._checkedScratch;
|
|
5624
|
+
checked.clear();
|
|
5594
5625
|
for (const cell of candidateCells) {
|
|
5595
5626
|
const bucket = spatialGrid.get(cell);
|
|
5596
5627
|
if (!bucket) continue;
|
|
@@ -5779,7 +5810,8 @@ var PhysicsSystem = class {
|
|
|
5779
5810
|
const circleCy = ct.y + cc.offsetY;
|
|
5780
5811
|
const circleAABB2 = { cx: circleCx, cy: circleCy, hw: cc.radius, hh: cc.radius };
|
|
5781
5812
|
const candidateCells = this.getCells(circleAABB2.cx, circleAABB2.cy, circleAABB2.hw, circleAABB2.hh);
|
|
5782
|
-
const checked =
|
|
5813
|
+
const checked = this._checkedScratch;
|
|
5814
|
+
checked.clear();
|
|
5783
5815
|
for (const cell of candidateCells) {
|
|
5784
5816
|
const bucket = spatialGrid.get(cell);
|
|
5785
5817
|
if (!bucket) continue;
|
|
@@ -5963,7 +5995,8 @@ var PhysicsSystem = class {
|
|
|
5963
5995
|
const capHw = cc.width / 2;
|
|
5964
5996
|
const capHh = cc.height / 2;
|
|
5965
5997
|
const candidateCells = this.getCells(capCx, capCy, capHw, capHh);
|
|
5966
|
-
const checked =
|
|
5998
|
+
const checked = this._checkedScratch;
|
|
5999
|
+
checked.clear();
|
|
5967
6000
|
for (const cell of candidateCells) {
|
|
5968
6001
|
const bucket = spatialGrid.get(cell);
|
|
5969
6002
|
if (!bucket) continue;
|
|
@@ -6202,7 +6235,8 @@ var PhysicsSystem = class {
|
|
|
6202
6235
|
const polyCx = (minX + maxX) / 2;
|
|
6203
6236
|
const polyCy = (minY + maxY) / 2;
|
|
6204
6237
|
const candidateCells = this.getCells(polyCx, polyCy, polyHw, polyHh);
|
|
6205
|
-
const checked =
|
|
6238
|
+
const checked = this._checkedScratch;
|
|
6239
|
+
checked.clear();
|
|
6206
6240
|
for (const cell of candidateCells) {
|
|
6207
6241
|
const bucket = spatialGrid.get(cell);
|
|
6208
6242
|
if (!bucket) continue;
|
|
@@ -6457,7 +6491,8 @@ var PhysicsSystem = class {
|
|
|
6457
6491
|
const triCx = (minX + maxX) / 2;
|
|
6458
6492
|
const triCy = (minY + maxY) / 2;
|
|
6459
6493
|
const candidateCells = this.getCells(triCx, triCy, triHw, triHh);
|
|
6460
|
-
const checked =
|
|
6494
|
+
const checked = this._checkedScratch;
|
|
6495
|
+
checked.clear();
|
|
6461
6496
|
for (const cell of candidateCells) {
|
|
6462
6497
|
const bucket = spatialGrid.get(cell);
|
|
6463
6498
|
if (!bucket) continue;
|
|
@@ -6956,7 +6991,8 @@ var PhysicsSystem = class {
|
|
|
6956
6991
|
this.hooks.onContactModify(m);
|
|
6957
6992
|
}
|
|
6958
6993
|
}
|
|
6959
|
-
const solverBodies =
|
|
6994
|
+
const solverBodies = this._solverBodies;
|
|
6995
|
+
solverBodies.clear();
|
|
6960
6996
|
for (const id of allBox) {
|
|
6961
6997
|
const rb = world.getComponent(id, "RigidBody");
|
|
6962
6998
|
const t = world.getComponent(id, "Transform");
|
|
@@ -7264,7 +7300,8 @@ var PhysicsSystem = class {
|
|
|
7264
7300
|
(Math.max(startCx, endCx) - Math.min(startCx, endCx)) / 2 + hw,
|
|
7265
7301
|
(Math.max(startCy, endCy) - Math.min(startCy, endCy)) / 2 + hh
|
|
7266
7302
|
);
|
|
7267
|
-
const checked =
|
|
7303
|
+
const checked = this._checkedScratch;
|
|
7304
|
+
checked.clear();
|
|
7268
7305
|
for (const cell of sweepCells) {
|
|
7269
7306
|
const bucket = spatialGrid.get(cell);
|
|
7270
7307
|
if (!bucket) continue;
|
|
@@ -7345,7 +7382,8 @@ var PhysicsSystem = class {
|
|
|
7345
7382
|
hh: col.height / 2
|
|
7346
7383
|
};
|
|
7347
7384
|
const candidateCells = this.getCells(probeAABB.cx, probeAABB.cy, probeAABB.hw, probeAABB.hh);
|
|
7348
|
-
const checked =
|
|
7385
|
+
const checked = this._checkedScratch;
|
|
7386
|
+
checked.clear();
|
|
7349
7387
|
outer: for (const cell of candidateCells) {
|
|
7350
7388
|
const bucket = spatialGrid.get(cell);
|
|
7351
7389
|
if (!bucket) continue;
|
|
@@ -7379,7 +7417,8 @@ var PhysicsSystem = class {
|
|
|
7379
7417
|
hh: cap.height / 2
|
|
7380
7418
|
};
|
|
7381
7419
|
const candidateCells = this.getCells(probeAABB.cx, probeAABB.cy, probeAABB.hw, probeAABB.hh);
|
|
7382
|
-
const checked =
|
|
7420
|
+
const checked = this._checkedScratch;
|
|
7421
|
+
checked.clear();
|
|
7383
7422
|
outerCap: for (const cell of candidateCells) {
|
|
7384
7423
|
const bucket = spatialGrid.get(cell);
|
|
7385
7424
|
if (!bucket) continue;
|
|
@@ -7723,10 +7762,16 @@ var PhysicsSystem = class {
|
|
|
7723
7762
|
this.events?.emit("collisionExit", { a, b, normalX: 0, normalY: 0 });
|
|
7724
7763
|
}
|
|
7725
7764
|
}
|
|
7726
|
-
|
|
7765
|
+
{
|
|
7766
|
+
const prev = this.activeCollisionPairs;
|
|
7767
|
+
this.activeCollisionPairs = currentCollisionPairs;
|
|
7768
|
+
this._currentCollisionPairs = prev;
|
|
7769
|
+
}
|
|
7727
7770
|
const allWithCollider = world.query("Transform", "BoxCollider");
|
|
7728
|
-
const currentTriggerPairs =
|
|
7729
|
-
|
|
7771
|
+
const currentTriggerPairs = this._currentTriggerPairs;
|
|
7772
|
+
currentTriggerPairs.clear();
|
|
7773
|
+
const triggerNormals = this._triggerNormals;
|
|
7774
|
+
triggerNormals.clear();
|
|
7730
7775
|
for (let i = 0; i < allWithCollider.length; i++) {
|
|
7731
7776
|
for (let j = i + 1; j < allWithCollider.length; j++) {
|
|
7732
7777
|
const ia = allWithCollider[i];
|
|
@@ -7762,10 +7807,16 @@ var PhysicsSystem = class {
|
|
|
7762
7807
|
for (const [key, [a, b]] of this.activeTriggerPairs) {
|
|
7763
7808
|
if (!currentTriggerPairs.has(key)) this.events?.emit("triggerExit", { a, b, normalX: 0, normalY: 0 });
|
|
7764
7809
|
}
|
|
7765
|
-
|
|
7810
|
+
{
|
|
7811
|
+
const prev = this.activeTriggerPairs;
|
|
7812
|
+
this.activeTriggerPairs = currentTriggerPairs;
|
|
7813
|
+
this._currentTriggerPairs = prev;
|
|
7814
|
+
}
|
|
7766
7815
|
if (allCircle.length > 0) {
|
|
7767
|
-
const currentCirclePairs =
|
|
7768
|
-
|
|
7816
|
+
const currentCirclePairs = this._currentCirclePairs;
|
|
7817
|
+
currentCirclePairs.clear();
|
|
7818
|
+
const circleNormals = this._circleNormals;
|
|
7819
|
+
circleNormals.clear();
|
|
7769
7820
|
for (let i = 0; i < allCircle.length; i++) {
|
|
7770
7821
|
for (let j = i + 1; j < allCircle.length; j++) {
|
|
7771
7822
|
const ia = allCircle[i];
|
|
@@ -7832,14 +7883,19 @@ var PhysicsSystem = class {
|
|
|
7832
7883
|
for (const [key, [a, b]] of this.activeCirclePairs) {
|
|
7833
7884
|
if (!currentCirclePairs.has(key)) this.events?.emit("circleExit", { a, b, normalX: 0, normalY: 0 });
|
|
7834
7885
|
}
|
|
7835
|
-
|
|
7886
|
+
{
|
|
7887
|
+
const prev = this.activeCirclePairs;
|
|
7888
|
+
this.activeCirclePairs = currentCirclePairs;
|
|
7889
|
+
this._currentCirclePairs = prev;
|
|
7890
|
+
}
|
|
7836
7891
|
} else if (this.activeCirclePairs.size > 0) {
|
|
7837
7892
|
for (const [, [a, b]] of this.activeCirclePairs) this.events?.emit("circleExit", { a, b, normalX: 0, normalY: 0 });
|
|
7838
|
-
this.activeCirclePairs
|
|
7893
|
+
this.activeCirclePairs.clear();
|
|
7839
7894
|
}
|
|
7840
7895
|
const allCompound = world.query("Transform", "CompoundCollider");
|
|
7841
7896
|
if (allCompound.length > 0) {
|
|
7842
|
-
const currentCompoundPairs =
|
|
7897
|
+
const currentCompoundPairs = this._currentCompoundPairs;
|
|
7898
|
+
currentCompoundPairs.clear();
|
|
7843
7899
|
const allBoxEntities = world.query("Transform", "BoxCollider");
|
|
7844
7900
|
for (const cid of allCompound) {
|
|
7845
7901
|
const cc = world.getComponent(cid, "CompoundCollider");
|
|
@@ -7914,13 +7970,18 @@ var PhysicsSystem = class {
|
|
|
7914
7970
|
for (const [key, [a, b]] of this.activeCompoundPairs) {
|
|
7915
7971
|
if (!currentCompoundPairs.has(key)) this.events?.emit("compoundExit", { a, b });
|
|
7916
7972
|
}
|
|
7917
|
-
|
|
7973
|
+
{
|
|
7974
|
+
const prev = this.activeCompoundPairs;
|
|
7975
|
+
this.activeCompoundPairs = currentCompoundPairs;
|
|
7976
|
+
this._currentCompoundPairs = prev;
|
|
7977
|
+
}
|
|
7918
7978
|
} else if (this.activeCompoundPairs.size > 0) {
|
|
7919
7979
|
for (const [, [a, b]] of this.activeCompoundPairs) this.events?.emit("compoundExit", { a, b });
|
|
7920
|
-
this.activeCompoundPairs
|
|
7980
|
+
this.activeCompoundPairs.clear();
|
|
7921
7981
|
}
|
|
7922
7982
|
if (allCapsule.length > 0) {
|
|
7923
|
-
const currentCapsulePairs =
|
|
7983
|
+
const currentCapsulePairs = this._currentCapsulePairs;
|
|
7984
|
+
currentCapsulePairs.clear();
|
|
7924
7985
|
const allBoxForCapsule = world.query("Transform", "BoxCollider");
|
|
7925
7986
|
for (const cid of allCapsule) {
|
|
7926
7987
|
const cc = world.getComponent(cid, "CapsuleCollider");
|
|
@@ -7958,14 +8019,19 @@ var PhysicsSystem = class {
|
|
|
7958
8019
|
for (const [key, [a, b]] of this.activeCapsulePairs) {
|
|
7959
8020
|
if (!currentCapsulePairs.has(key)) this.events?.emit("capsuleExit", { a, b });
|
|
7960
8021
|
}
|
|
7961
|
-
|
|
8022
|
+
{
|
|
8023
|
+
const prev = this.activeCapsulePairs;
|
|
8024
|
+
this.activeCapsulePairs = currentCapsulePairs;
|
|
8025
|
+
this._currentCapsulePairs = prev;
|
|
8026
|
+
}
|
|
7962
8027
|
} else if (this.activeCapsulePairs.size > 0) {
|
|
7963
8028
|
for (const [, [a, b]] of this.activeCapsulePairs) this.events?.emit("capsuleExit", { a, b });
|
|
7964
|
-
this.activeCapsulePairs
|
|
8029
|
+
this.activeCapsulePairs.clear();
|
|
7965
8030
|
}
|
|
7966
8031
|
const allPolygonEntities = [...allPolygon, ...allTriangle];
|
|
7967
8032
|
if (allPolygonEntities.length > 0) {
|
|
7968
|
-
const currentPolyPairs =
|
|
8033
|
+
const currentPolyPairs = this._currentPolygonPairs;
|
|
8034
|
+
currentPolyPairs.clear();
|
|
7969
8035
|
const allBoxForPoly = world.query("Transform", "BoxCollider");
|
|
7970
8036
|
for (const pid of allPolygonEntities) {
|
|
7971
8037
|
const isPoly = world.getComponent(pid, "ConvexPolygonCollider");
|
|
@@ -8046,10 +8112,14 @@ var PhysicsSystem = class {
|
|
|
8046
8112
|
for (const [key, [a, b]] of this.activePolygonPairs) {
|
|
8047
8113
|
if (!currentPolyPairs.has(key)) this.events?.emit("polygonExit", { a, b });
|
|
8048
8114
|
}
|
|
8049
|
-
|
|
8115
|
+
{
|
|
8116
|
+
const prev = this.activePolygonPairs;
|
|
8117
|
+
this.activePolygonPairs = currentPolyPairs;
|
|
8118
|
+
this._currentPolygonPairs = prev;
|
|
8119
|
+
}
|
|
8050
8120
|
} else if (this.activePolygonPairs.size > 0) {
|
|
8051
8121
|
for (const [, [a, b]] of this.activePolygonPairs) this.events?.emit("polygonExit", { a, b });
|
|
8052
|
-
this.activePolygonPairs
|
|
8122
|
+
this.activePolygonPairs.clear();
|
|
8053
8123
|
}
|
|
8054
8124
|
}
|
|
8055
8125
|
// ── Pair pruning ────────────────────────────────────────────────────────
|
package/dist/index.d.ts
CHANGED
|
@@ -67,6 +67,10 @@ interface GameProps$1 {
|
|
|
67
67
|
* - 'onDemand' — sleeps until input arrives or a component calls markDirty().
|
|
68
68
|
* Use for puzzle games, turn-based games, visual novels, level editors, or any
|
|
69
69
|
* scene where nothing changes unless the user acts. Saves battery and CPU.
|
|
70
|
+
*
|
|
71
|
+
* **Captured at mount.** This prop is read once when the Game mounts and
|
|
72
|
+
* baked into the loop. Changing it later has no effect — to switch modes,
|
|
73
|
+
* unmount and remount the Game (e.g. via a `key` change).
|
|
70
74
|
*/
|
|
71
75
|
mode?: GameLoopMode;
|
|
72
76
|
style?: CSSProperties;
|
|
@@ -499,7 +503,48 @@ interface SquashStretchProps {
|
|
|
499
503
|
}
|
|
500
504
|
declare function SquashStretch({ intensity, recovery }: SquashStretchProps): null;
|
|
501
505
|
|
|
502
|
-
type ParticlePreset = 'explosion' | 'spark' | 'smoke' | 'coinPickup' | 'jumpDust';
|
|
506
|
+
type ParticlePreset = 'explosion' | 'spark' | 'smoke' | 'coinPickup' | 'jumpDust' | 'fire' | 'magic' | 'rain' | 'snow' | 'confetti' | 'sparkle' | 'heal' | 'damage' | 'pickup' | 'fountain' | 'trail';
|
|
507
|
+
interface ParticleEmitterConfig {
|
|
508
|
+
rate?: number;
|
|
509
|
+
speed?: number;
|
|
510
|
+
spread?: number;
|
|
511
|
+
angle?: number;
|
|
512
|
+
particleLife?: number;
|
|
513
|
+
particleSize?: number;
|
|
514
|
+
color?: string;
|
|
515
|
+
gravity?: number;
|
|
516
|
+
maxParticles?: number;
|
|
517
|
+
/** Colors to interpolate through over particle lifetime. */
|
|
518
|
+
colorOverLife?: string[];
|
|
519
|
+
/** Start/end size ratios for per-particle size curve (end is multiplier of particleSize). */
|
|
520
|
+
sizeOverLife?: {
|
|
521
|
+
start: number;
|
|
522
|
+
end: number;
|
|
523
|
+
};
|
|
524
|
+
/** Blend mode for the emitter (additive for glows, normal for solid). */
|
|
525
|
+
blendMode?: 'normal' | 'additive';
|
|
526
|
+
/** Particle shape: 'soft' gradient, 'circle' hard disc, 'square' quad. */
|
|
527
|
+
particleShape?: 'soft' | 'circle' | 'square';
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Ready-made particle configurations. Pass via the `preset` prop on
|
|
531
|
+
* `<ParticleEmitter>`:
|
|
532
|
+
*
|
|
533
|
+
* ```tsx
|
|
534
|
+
* <ParticleEmitter preset="fire" />
|
|
535
|
+
* <ParticleEmitter preset="explosion" color="#8bc34a" /> // overrides
|
|
536
|
+
* ```
|
|
537
|
+
*
|
|
538
|
+
* Individual props always override preset values — presets are defaults.
|
|
539
|
+
*
|
|
540
|
+
* ## Catalog
|
|
541
|
+
*
|
|
542
|
+
* Action / combat: `explosion`, `spark`, `damage`, `heal`, `magic`
|
|
543
|
+
* Environment: `fire`, `smoke`, `rain`, `snow`, `fountain`
|
|
544
|
+
* UI / reward: `coinPickup`, `pickup`, `sparkle`, `confetti`
|
|
545
|
+
* Character: `jumpDust`, `trail`
|
|
546
|
+
*/
|
|
547
|
+
declare const PARTICLE_PRESETS: Record<ParticlePreset, ParticleEmitterConfig>;
|
|
503
548
|
|
|
504
549
|
interface ParticleEmitterProps {
|
|
505
550
|
active?: boolean;
|
|
@@ -3096,6 +3141,143 @@ declare function deleteSavedScene(key: string): boolean;
|
|
|
3096
3141
|
*/
|
|
3097
3142
|
declare function listSavedScenes(prefix?: string): string[];
|
|
3098
3143
|
|
|
3144
|
+
type HUDPosition = 'topLeft' | 'topCenter' | 'topRight' | 'centerLeft' | 'center' | 'centerRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight';
|
|
3145
|
+
interface HUDProps {
|
|
3146
|
+
/**
|
|
3147
|
+
* Whether the HUD fades out during scene transitions. Default true. When a
|
|
3148
|
+
* `SceneTransitionOverlay` is active or `usePause` is paused, the HUD will
|
|
3149
|
+
* dim to `dimmedOpacity` to get out of the way.
|
|
3150
|
+
*/
|
|
3151
|
+
dimDuringTransitions?: boolean;
|
|
3152
|
+
/** Opacity when dimmed. Default 0.25. */
|
|
3153
|
+
dimmedOpacity?: number;
|
|
3154
|
+
/** Whether the HUD is currently visible. Default true. */
|
|
3155
|
+
visible?: boolean;
|
|
3156
|
+
/** Whether to apply CSS `env(safe-area-inset-*)` padding. Default true on touch. */
|
|
3157
|
+
safeArea?: boolean;
|
|
3158
|
+
/** Extra padding around all zones in CSS pixels. Default 12. */
|
|
3159
|
+
padding?: number;
|
|
3160
|
+
/** Additional style for the HUD root. */
|
|
3161
|
+
style?: CSSProperties;
|
|
3162
|
+
/** Additional CSS class. */
|
|
3163
|
+
className?: string;
|
|
3164
|
+
children?: ReactNode;
|
|
3165
|
+
}
|
|
3166
|
+
/**
|
|
3167
|
+
* Heads-up-display root. Positions a full-screen overlay over the game canvas
|
|
3168
|
+
* and provides layout zones via {@link HUDZone}. Integrates automatically with
|
|
3169
|
+
* CubeForge primitives:
|
|
3170
|
+
*
|
|
3171
|
+
* - Fades out during scene transitions (via `dimDuringTransitions`)
|
|
3172
|
+
* - Respects `prefers-reduced-motion` for fade timing
|
|
3173
|
+
* - Honors mobile safe-area insets when `safeArea` is on
|
|
3174
|
+
*
|
|
3175
|
+
* @example
|
|
3176
|
+
* ```tsx
|
|
3177
|
+
* <Stage>
|
|
3178
|
+
* <HUD>
|
|
3179
|
+
* <HUDZone position="topLeft">
|
|
3180
|
+
* <HUDBar value={hp} max={100} label="HP" color="#ef5350" />
|
|
3181
|
+
* </HUDZone>
|
|
3182
|
+
* <HUDZone position="topRight">
|
|
3183
|
+
* <span>Score: {score}</span>
|
|
3184
|
+
* </HUDZone>
|
|
3185
|
+
* <HUDZone position="bottomCenter">
|
|
3186
|
+
* <button onClick={onJump}>Jump</button>
|
|
3187
|
+
* </HUDZone>
|
|
3188
|
+
* </HUD>
|
|
3189
|
+
* </Stage>
|
|
3190
|
+
* ```
|
|
3191
|
+
*/
|
|
3192
|
+
declare function HUD({ dimDuringTransitions, dimmedOpacity, visible, safeArea, padding, style, className, children, }: HUDProps): react_jsx_runtime.JSX.Element;
|
|
3193
|
+
interface HUDZoneProps {
|
|
3194
|
+
/** Where to anchor this zone. Default 'topLeft'. */
|
|
3195
|
+
position?: HUDPosition;
|
|
3196
|
+
/** Direction children lay out. Default 'row' for top/bottom, 'column' for left/right/center. */
|
|
3197
|
+
direction?: 'row' | 'column';
|
|
3198
|
+
/** Gap between children in CSS pixels. Default 8. */
|
|
3199
|
+
gap?: number;
|
|
3200
|
+
/** Allow pointer events on zone contents (buttons, sliders). Default true for this zone. */
|
|
3201
|
+
interactive?: boolean;
|
|
3202
|
+
/** Override style for the zone. */
|
|
3203
|
+
style?: CSSProperties;
|
|
3204
|
+
/** Additional CSS class. */
|
|
3205
|
+
className?: string;
|
|
3206
|
+
children?: ReactNode;
|
|
3207
|
+
}
|
|
3208
|
+
/**
|
|
3209
|
+
* Positioned content zone inside a {@link HUD}. Nine anchors available
|
|
3210
|
+
* (topLeft, topCenter, topRight, centerLeft, center, centerRight, bottomLeft,
|
|
3211
|
+
* bottomCenter, bottomRight). Honors the parent HUD's padding and safe-area.
|
|
3212
|
+
*/
|
|
3213
|
+
declare function HUDZone({ position, direction, gap, interactive, style, className, children, }: HUDZoneProps): react_jsx_runtime.JSX.Element;
|
|
3214
|
+
interface HUDBarProps {
|
|
3215
|
+
/** Current value. */
|
|
3216
|
+
value: number;
|
|
3217
|
+
/** Maximum value. */
|
|
3218
|
+
max: number;
|
|
3219
|
+
/** Optional label shown on top of the bar. */
|
|
3220
|
+
label?: string;
|
|
3221
|
+
/** Bar color. Default '#4fc3f7'. */
|
|
3222
|
+
color?: string;
|
|
3223
|
+
/** Track (empty) color. Default 'rgba(255,255,255,0.08)'. */
|
|
3224
|
+
trackColor?: string;
|
|
3225
|
+
/** Bar width in CSS pixels. Default 180. */
|
|
3226
|
+
width?: number;
|
|
3227
|
+
/** Bar height in CSS pixels. Default 14. */
|
|
3228
|
+
height?: number;
|
|
3229
|
+
/** Show numeric value as "value / max". Default true. */
|
|
3230
|
+
showValue?: boolean;
|
|
3231
|
+
/** Reverse direction: fills right→left. Default false. */
|
|
3232
|
+
rtl?: boolean;
|
|
3233
|
+
/** Round the bar corners. Default true. */
|
|
3234
|
+
rounded?: boolean;
|
|
3235
|
+
/** Smooth transition when value changes. Default true. */
|
|
3236
|
+
animated?: boolean;
|
|
3237
|
+
/** Additional style. */
|
|
3238
|
+
style?: CSSProperties;
|
|
3239
|
+
}
|
|
3240
|
+
/**
|
|
3241
|
+
* A simple value bar for HP, stamina, XP, progress, etc. Meant to be dropped
|
|
3242
|
+
* inside a {@link HUDZone} without any extra styling. Animates smoothly by
|
|
3243
|
+
* default; respects `prefers-reduced-motion` transparently via CSS.
|
|
3244
|
+
*
|
|
3245
|
+
* @example
|
|
3246
|
+
* ```tsx
|
|
3247
|
+
* <HUDZone position="topLeft">
|
|
3248
|
+
* <HUDBar value={hp} max={100} label="HP" color="#ef5350" />
|
|
3249
|
+
* <HUDBar value={mana} max={50} label="MP" color="#4fc3f7" />
|
|
3250
|
+
* </HUDZone>
|
|
3251
|
+
* ```
|
|
3252
|
+
*/
|
|
3253
|
+
declare function HUDBar({ value, max, label, color, trackColor, width, height, showValue, rtl, rounded, animated, style, }: HUDBarProps): react_jsx_runtime.JSX.Element;
|
|
3254
|
+
interface HUDCounterProps {
|
|
3255
|
+
/** Numeric value to display. */
|
|
3256
|
+
value: number;
|
|
3257
|
+
/** Optional icon or emoji shown before the value. */
|
|
3258
|
+
icon?: ReactNode;
|
|
3259
|
+
/** Optional label shown after the value. */
|
|
3260
|
+
label?: string;
|
|
3261
|
+
/** Flash briefly when the value changes. Default true. */
|
|
3262
|
+
pulse?: boolean;
|
|
3263
|
+
/** Value color. Default '#fff'. */
|
|
3264
|
+
color?: string;
|
|
3265
|
+
/** Font size in CSS pixels. Default 18. */
|
|
3266
|
+
fontSize?: number;
|
|
3267
|
+
style?: CSSProperties;
|
|
3268
|
+
}
|
|
3269
|
+
/**
|
|
3270
|
+
* A numeric counter widget for score, coins, ammo, etc.
|
|
3271
|
+
*
|
|
3272
|
+
* @example
|
|
3273
|
+
* ```tsx
|
|
3274
|
+
* <HUDZone position="topRight">
|
|
3275
|
+
* <HUDCounter icon="🪙" value={coins} />
|
|
3276
|
+
* </HUDZone>
|
|
3277
|
+
* ```
|
|
3278
|
+
*/
|
|
3279
|
+
declare function HUDCounter({ value, icon, label, pulse, color, fontSize, style, }: HUDCounterProps): react_jsx_runtime.JSX.Element;
|
|
3280
|
+
|
|
3099
3281
|
declare function playClip(world: ECSWorld, entityId: EntityId, clipName: string): void;
|
|
3100
3282
|
declare function setAnimationState(world: ECSWorld, entityId: EntityId, stateName: string): void;
|
|
3101
3283
|
declare function setAnimatorParam(world: ECSWorld, entityId: EntityId, name: string, value: AnimatorParamValue): void;
|
|
@@ -3202,4 +3384,4 @@ declare function useRemotePlayer(config: {
|
|
|
3202
3384
|
opts?: RemotePlayerOptions;
|
|
3203
3385
|
}): RemotePlayerControls;
|
|
3204
3386
|
|
|
3205
|
-
export { A11yNode, type A11yNodeProps, type AccessibilityControls, AnimatedSprite, type AnimatedSpriteProps, Animation, type AnimationSet, Animator, AssetLoader, type BoundInputMap, BoxCollider, Camera2D, type CameraControls, type CameraLookaheadOptions, CameraZone, CapsuleCollider, Checkpoint, Circle, CircleCollider, type ComboDetectorResult, CompoundCollider, ConvexCollider, type CoordinateHelpers, type CoroutineControls, type CoroutineFactory, type CoroutineYield, type DraggableControls, type DraggableOptions, type DroppableControls, type DroppableOptions, EditableText, type EditableTextProps, Entity, type ExportOptions, FocusRing, type FocusRingProps, type FocusableOptions, Game, type GameControls, type GamepadState, type GestureHandlers, type GestureOptions, Gradient, type GridCell, type GridControls, type GridOptions, type HMRControls, HalfSpaceCollider, HeightFieldCollider, type HistoryControls, type HistoryOptions, type HoverableControls, type HoverableOptions, type InputContextControls, Joint, type KeyboardFocusControls, Line, Mask, MovingPlatform, type NetworkSyncOptions, NineSlice, ParallaxLayer, ParticleEmitter, type ParticlePreset, type PauseControls, type PinchEvent, Polygon, type PreloadState, type ProfilerData, type RemotePlayerControls, type RemotePlayerOptions, RigidBody, type SceneManagerControls, type SceneSaveOptions, type SceneTransitionControls, SceneTransitionOverlay, ScreenFlash, type ScreenFlashHandle, Script, SegmentCollider, type SelectOptions, Selection, type SelectionControls, type SelectionProps, type SnapControls, type SnapOptions, type SnapResult, type SnapshotControls, Sprite, type SpriteAtlas, SquashStretch, type SquashStretchControls, Stage, type SwipeEvent, Text, type TiledLayer, type TiledObject, Tilemap, type TimerControls, type TouchControls, Trail, Transform, TransformHandles, type TransformHandlesProps, type TransitionEffect, TriMeshCollider, TriangleCollider, type TurnSystemControls, type TurnSystemOptions, VectorPath, type VectorPathProps, type VirtualInputState, VirtualJoystick, type VirtualJoystickProps, type Waypoint, World, createAtlas, defineAnimations, definePrefab, deleteSavedScene, downloadCanvas, exportToBlob, exportToDataURL, listSavedScenes, loadScene, loadSceneFromLocalStorage, playClip, saveScene, saveSceneToLocalStorage, setAnimationState, setAnimatorParam, useAccessibility, useAudioListener, useCamera, useCameraLookahead, useComboDetector, useCoordinates, useCoroutine, useDestroyEntity, useDraggable, useDroppable, useEntity, useEvent, useEvents, useFocusable, useGame, useGamepad, useGamepadHaptics, useGestures, useGrid, useHMR, useHistory, useHitstop, useHoverable, useInput, useInputBuffer, useInputContext, useInputMap, useInputRecorder, useKeyboardFocus, useLocalMultiplayer, useNetworkSync, useParent, usePause, usePlayerInput, usePostProcess, usePreload, useProfiler, useRemotePlayer, useSceneManager, useSceneTransition, useSelection, useSnap, useSnapshot, useSquashStretch, useTimer, useTouch, useTurnSystem, useVirtualInput, useWebGLPostProcess, useWorldQuery, wait, waitFrames, waitUntil };
|
|
3387
|
+
export { A11yNode, type A11yNodeProps, type AccessibilityControls, AnimatedSprite, type AnimatedSpriteProps, Animation, type AnimationSet, Animator, AssetLoader, type BoundInputMap, BoxCollider, Camera2D, type CameraControls, type CameraLookaheadOptions, CameraZone, CapsuleCollider, Checkpoint, Circle, CircleCollider, type ComboDetectorResult, CompoundCollider, ConvexCollider, type CoordinateHelpers, type CoroutineControls, type CoroutineFactory, type CoroutineYield, type DraggableControls, type DraggableOptions, type DroppableControls, type DroppableOptions, EditableText, type EditableTextProps, Entity, type ExportOptions, FocusRing, type FocusRingProps, type FocusableOptions, Game, type GameControls, type GamepadState, type GestureHandlers, type GestureOptions, Gradient, type GridCell, type GridControls, type GridOptions, type HMRControls, HUD, HUDBar, type HUDBarProps, HUDCounter, type HUDCounterProps, type HUDPosition, type HUDProps, HUDZone, type HUDZoneProps, HalfSpaceCollider, HeightFieldCollider, type HistoryControls, type HistoryOptions, type HoverableControls, type HoverableOptions, type InputContextControls, Joint, type KeyboardFocusControls, Line, Mask, MovingPlatform, type NetworkSyncOptions, NineSlice, PARTICLE_PRESETS, ParallaxLayer, ParticleEmitter, type ParticleEmitterConfig, type ParticlePreset, type PauseControls, type PinchEvent, Polygon, type PreloadState, type ProfilerData, type RemotePlayerControls, type RemotePlayerOptions, RigidBody, type SceneManagerControls, type SceneSaveOptions, type SceneTransitionControls, SceneTransitionOverlay, ScreenFlash, type ScreenFlashHandle, Script, SegmentCollider, type SelectOptions, Selection, type SelectionControls, type SelectionProps, type SnapControls, type SnapOptions, type SnapResult, type SnapshotControls, Sprite, type SpriteAtlas, SquashStretch, type SquashStretchControls, Stage, type SwipeEvent, Text, type TiledLayer, type TiledObject, Tilemap, type TimerControls, type TouchControls, Trail, Transform, TransformHandles, type TransformHandlesProps, type TransitionEffect, TriMeshCollider, TriangleCollider, type TurnSystemControls, type TurnSystemOptions, VectorPath, type VectorPathProps, type VirtualInputState, VirtualJoystick, type VirtualJoystickProps, type Waypoint, World, createAtlas, defineAnimations, definePrefab, deleteSavedScene, downloadCanvas, exportToBlob, exportToDataURL, listSavedScenes, loadScene, loadSceneFromLocalStorage, playClip, saveScene, saveSceneToLocalStorage, setAnimationState, setAnimatorParam, useAccessibility, useAudioListener, useCamera, useCameraLookahead, useComboDetector, useCoordinates, useCoroutine, useDestroyEntity, useDraggable, useDroppable, useEntity, useEvent, useEvents, useFocusable, useGame, useGamepad, useGamepadHaptics, useGestures, useGrid, useHMR, useHistory, useHitstop, useHoverable, useInput, useInputBuffer, useInputContext, useInputMap, useInputRecorder, useKeyboardFocus, useLocalMultiplayer, useNetworkSync, useParent, usePause, usePlayerInput, usePostProcess, usePreload, useProfiler, useRemotePlayer, useSceneManager, useSceneTransition, useSelection, useSnap, useSnapshot, useSquashStretch, useTimer, useTouch, useTurnSystem, useVirtualInput, useWebGLPostProcess, useWorldQuery, wait, waitFrames, waitUntil };
|