lecodes-sdk 0.20.0 → 1.0.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/global.d.ts +48 -5
- package/dist/inject.js +361 -260
- package/dist/types/audio/Bus.d.ts +45 -0
- package/dist/types/audio/Sound.d.ts +28 -0
- package/dist/types/audio/Voice.d.ts +27 -0
- package/dist/types/audio/audio.d.ts +83 -0
- package/dist/types/audio/support.d.ts +1 -0
- package/dist/types/canvas/Canvas.d.ts +2 -0
- package/dist/types/gl/DecalSet.d.ts +148 -0
- package/dist/types/gl/Geometry.d.ts +17 -0
- package/dist/types/gl/Light.d.ts +7 -0
- package/dist/types/gl/Lightmap.d.ts +9 -0
- package/dist/types/gl/Material.d.ts +90 -2
- package/dist/types/gl/Mesh.d.ts +18 -1
- package/dist/types/gl/Model.d.ts +34 -0
- package/dist/types/gl/Particles.d.ts +13 -0
- package/dist/types/gl/Scene.d.ts +23 -0
- package/dist/types/gl/Texture.d.ts +29 -1
- package/dist/types/gl/animation/AnimationClip.d.ts +25 -12
- package/dist/types/gl/animation/DynamicBone.d.ts +173 -0
- package/dist/types/gl/{IK.d.ts → animation/IK.d.ts} +4 -4
- package/dist/types/gl/{Locomotion.d.ts → animation/Locomotion.d.ts} +6 -6
- package/dist/types/gl/animation/core.d.ts +15 -10
- package/dist/types/gl/audio/AudioSource.d.ts +60 -0
- package/dist/types/gl/audio/AudioZone.d.ts +32 -0
- package/dist/types/gl/audio/SceneAudio.d.ts +11 -0
- package/dist/types/gl/{NavAgent.d.ts → nav/NavAgent.d.ts} +4 -4
- package/dist/types/gl/{NavMesh.d.ts → nav/NavMesh.d.ts} +4 -4
- package/dist/types/gl/{CharacterController.d.ts → physics/CharacterController.d.ts} +5 -5
- package/dist/types/gl/{Physics.d.ts → physics/Physics.d.ts} +6 -5
- package/dist/types/gl/{Ragdoll.d.ts → physics/Ragdoll.d.ts} +4 -4
- package/dist/types/gl/{Shape.d.ts → physics/Shape.d.ts} +3 -3
- package/dist/types/gl/{Trigger.d.ts → physics/Trigger.d.ts} +2 -2
- package/dist/types/gl/state.d.ts +0 -1
- package/dist/types/gl/{Terrain.d.ts → terrain/Terrain.d.ts} +6 -6
- package/dist/types/gl/{terrainMesh.d.ts → terrain/terrainMesh.d.ts} +1 -1
- package/dist/types/gl/vehicle/Vehicle.d.ts +300 -0
- package/dist/types/gl/vehicle/Wheel.d.ts +147 -0
- package/dist/types/inject.d.ts +33 -21
- package/dist/types/runtime/files.d.ts +24 -1
- package/dist/types/runtime/input.d.ts +11 -0
- package/dist/types/scene/defineScene.d.ts +10 -3
- package/dist/types/ui/UIImage.d.ts +15 -5
- package/dist/types.json +1 -1
- package/package.json +1 -1
- package/prompts/README.md +142 -142
- package/prompts/dist/2d-game.md +408 -197
- package/prompts/dist/3d-app.md +491 -166
- package/prompts/dist/ar-app.md +373 -163
- package/prompts/dist/design.md +83 -87
- package/prompts/dist/ui-app.md +325 -136
- package/src/audio/Bus.ts +102 -0
- package/src/audio/Sound.ts +96 -0
- package/src/audio/Voice.ts +102 -0
- package/src/audio/audio.ts +161 -0
- package/src/audio/support.ts +6 -0
- package/src/bridges.d.ts +279 -32
- package/src/canvas/Canvas.ts +21 -0
- package/src/compile/__tests__/compile.test.ts +11 -0
- package/src/compile/compileProject.ts +30 -15
- package/src/compile/header.ts +6 -3
- package/src/compile/index.ts +4 -0
- package/src/compile/sceneEditor.ts +42 -1
- package/src/core/Aspect.ts +33 -8
- package/src/g2/Scene2D.ts +7 -0
- package/src/gl/CameraPlace.ts +52 -52
- package/src/gl/DecalSet.ts +360 -0
- package/src/gl/Geometry.ts +348 -279
- package/src/gl/Light.ts +16 -0
- package/src/gl/Lightmap.ts +35 -7
- package/src/gl/Material.ts +173 -4
- package/src/gl/Mesh.ts +120 -83
- package/src/gl/Model.ts +33 -1
- package/src/gl/Node.ts +1 -1
- package/src/gl/Particles.ts +21 -3
- package/src/gl/Scene.ts +41 -7
- package/src/gl/Texture.ts +43 -3
- package/src/gl/animation/AnimationClip.ts +43 -20
- package/src/gl/animation/Animator.ts +4 -3
- package/src/gl/animation/DynamicBone.ts +459 -0
- package/src/gl/{IK.ts → animation/IK.ts} +4 -4
- package/src/gl/{Locomotion.ts → animation/Locomotion.ts} +7 -7
- package/src/gl/animation/core.ts +20 -15
- package/src/gl/audio/AudioSource.ts +113 -0
- package/src/gl/audio/AudioZone.ts +75 -0
- package/src/gl/audio/SceneAudio.ts +26 -0
- package/src/gl/{NavAgent.ts → nav/NavAgent.ts} +5 -5
- package/src/gl/{NavMesh.ts → nav/NavMesh.ts} +8 -8
- package/src/gl/{CharacterController.ts → physics/CharacterController.ts} +5 -5
- package/src/gl/{Physics.ts → physics/Physics.ts} +12 -5
- package/src/gl/{Ragdoll.ts → physics/Ragdoll.ts} +272 -270
- package/src/gl/{Shape.ts → physics/Shape.ts} +3 -3
- package/src/gl/{Trigger.ts → physics/Trigger.ts} +2 -2
- package/src/gl/{physicsEvents.ts → physics/physicsEvents.ts} +1 -1
- package/src/gl/scenarios.ts +291 -291
- package/src/gl/state.ts +1 -1
- package/src/gl/{Terrain.ts → terrain/Terrain.ts} +10 -10
- package/src/gl/{terrainMesh.ts → terrain/terrainMesh.ts} +1 -1
- package/src/gl/vehicle/Vehicle.ts +666 -0
- package/src/gl/vehicle/Wheel.ts +290 -0
- package/src/inject.ts +226 -212
- package/src/runtime/files.ts +32 -2
- package/src/runtime/input.ts +6 -1
- package/src/scene/defineScene.ts +26 -10
- package/src/scene/gizmos.ts +148 -148
- package/src/scene/level.ts +2 -2
- package/src/ui/UIImage.ts +21 -7
- package/dist/types/gl/Gearbox.d.ts +0 -86
- package/dist/types/gl/Vehicle.d.ts +0 -191
- package/dist/types/gl/Wheel.d.ts +0 -95
- package/src/gl/Gearbox.ts +0 -212
- package/src/gl/Vehicle.ts +0 -473
- package/src/gl/Wheel.ts +0 -240
- /package/dist/types/gl/{physicsEvents.d.ts → physics/physicsEvents.d.ts} +0 -0
package/dist/inject.js
CHANGED
|
@@ -1235,6 +1235,88 @@ var Color = {
|
|
|
1235
1235
|
}
|
|
1236
1236
|
};
|
|
1237
1237
|
|
|
1238
|
+
// src/core/events.ts
|
|
1239
|
+
var Emitter = class {
|
|
1240
|
+
_listeners = {};
|
|
1241
|
+
addEventListener(channel, callback) {
|
|
1242
|
+
const list = this._listeners[channel];
|
|
1243
|
+
if (list) list.push(callback);
|
|
1244
|
+
else this._listeners[channel] = [callback];
|
|
1245
|
+
}
|
|
1246
|
+
removeEventListener(channel, callback) {
|
|
1247
|
+
const list = this._listeners[channel];
|
|
1248
|
+
if (!list) return;
|
|
1249
|
+
const i = list.indexOf(callback);
|
|
1250
|
+
if (i >= 0) list.splice(i, 1);
|
|
1251
|
+
}
|
|
1252
|
+
/** Fire all listeners on a channel. Protected: only the owning class emits. */
|
|
1253
|
+
dispatch(channel, ...args) {
|
|
1254
|
+
const list = this._listeners[channel];
|
|
1255
|
+
if (!list) return;
|
|
1256
|
+
for (const fn of list.slice()) fn(...args);
|
|
1257
|
+
}
|
|
1258
|
+
hasListeners(channel) {
|
|
1259
|
+
const list = this._listeners[channel];
|
|
1260
|
+
return !!list && list.length > 0;
|
|
1261
|
+
}
|
|
1262
|
+
/** Drop every listener on every channel (used when the owning object is disposed). */
|
|
1263
|
+
clearListeners() {
|
|
1264
|
+
this._listeners = {};
|
|
1265
|
+
}
|
|
1266
|
+
};
|
|
1267
|
+
|
|
1268
|
+
// src/core/Aspect.ts
|
|
1269
|
+
var AspectHost = class extends Emitter {
|
|
1270
|
+
/** @internal class → instance, the authoritative store (named accessors mirror this). */
|
|
1271
|
+
_aspects = /* @__PURE__ */ new Map();
|
|
1272
|
+
/** Attach (and configure) an aspect, or reconfigure it if already present. Returns the node typed
|
|
1273
|
+
* as now-having that aspect (so no guard/`?.` is needed afterwards). Rejects a wrong target node. */
|
|
1274
|
+
aspect(ctor, opts) {
|
|
1275
|
+
const host = this;
|
|
1276
|
+
let inst = host._aspects.get(ctor);
|
|
1277
|
+
const fresh = inst === void 0;
|
|
1278
|
+
if (!inst) {
|
|
1279
|
+
inst = new ctor();
|
|
1280
|
+
inst.node = this;
|
|
1281
|
+
host._aspects.set(ctor, inst);
|
|
1282
|
+
const name = ctor.aspect;
|
|
1283
|
+
if (name) host[name] = inst;
|
|
1284
|
+
}
|
|
1285
|
+
if (opts) Object.assign(inst, opts);
|
|
1286
|
+
if (fresh) inst.onAttach?.();
|
|
1287
|
+
return this;
|
|
1288
|
+
}
|
|
1289
|
+
/** Safe access — undefined if the aspect isn't attached. */
|
|
1290
|
+
get(ctor) {
|
|
1291
|
+
return this._aspects.get(ctor);
|
|
1292
|
+
}
|
|
1293
|
+
/** Existence check AND type guard: inside `if (node.has(Physics))`, `node.physics` is present. */
|
|
1294
|
+
has(ctor) {
|
|
1295
|
+
return this._aspects.has(ctor);
|
|
1296
|
+
}
|
|
1297
|
+
/** Detach an aspect (runs its onDetach). Named `removeAspect` so it never collides with the
|
|
1298
|
+
* child-management `add`/`remove` semantics some node kinds expose. */
|
|
1299
|
+
removeAspect(ctor) {
|
|
1300
|
+
const inst = this._aspects.get(ctor);
|
|
1301
|
+
if (inst) {
|
|
1302
|
+
inst.onDetach?.();
|
|
1303
|
+
this._aspects.delete(ctor);
|
|
1304
|
+
const name = ctor.aspect;
|
|
1305
|
+
if (name) delete this[name];
|
|
1306
|
+
}
|
|
1307
|
+
return this;
|
|
1308
|
+
}
|
|
1309
|
+
};
|
|
1310
|
+
var Aspect = class {
|
|
1311
|
+
// NOTE: P has no `extends AspectHost` constraint on purpose — Emitter<E>'s generic
|
|
1312
|
+
// addEventListener makes a specific-event node (AspectHost<NodeEvents>) not assignable to
|
|
1313
|
+
// AspectHost<any>, which would reject every real node. P only types `this.node`; target
|
|
1314
|
+
// enforcement happens in aspect() via `this: Self extends TargetOf<A>`. Defaults to Node
|
|
1315
|
+
// (3D is the default engine) — a 2D aspect declares its own P, e.g. Aspect<'x', Sprite>.
|
|
1316
|
+
/** The node this aspect is attached to (set at attach time). */
|
|
1317
|
+
node;
|
|
1318
|
+
};
|
|
1319
|
+
|
|
1238
1320
|
// src/runtime/misc.ts
|
|
1239
1321
|
var toast = (msg) => _creatorUI.toast(msg);
|
|
1240
1322
|
var SvgSource = (svg) => ({ svg, tintColor: null });
|
|
@@ -1336,36 +1418,6 @@ var Input = {
|
|
|
1336
1418
|
}
|
|
1337
1419
|
};
|
|
1338
1420
|
|
|
1339
|
-
// src/core/events.ts
|
|
1340
|
-
var Emitter = class {
|
|
1341
|
-
_listeners = {};
|
|
1342
|
-
addEventListener(channel, callback) {
|
|
1343
|
-
const list = this._listeners[channel];
|
|
1344
|
-
if (list) list.push(callback);
|
|
1345
|
-
else this._listeners[channel] = [callback];
|
|
1346
|
-
}
|
|
1347
|
-
removeEventListener(channel, callback) {
|
|
1348
|
-
const list = this._listeners[channel];
|
|
1349
|
-
if (!list) return;
|
|
1350
|
-
const i = list.indexOf(callback);
|
|
1351
|
-
if (i >= 0) list.splice(i, 1);
|
|
1352
|
-
}
|
|
1353
|
-
/** Fire all listeners on a channel. Protected: only the owning class emits. */
|
|
1354
|
-
dispatch(channel, ...args) {
|
|
1355
|
-
const list = this._listeners[channel];
|
|
1356
|
-
if (!list) return;
|
|
1357
|
-
for (const fn of list.slice()) fn(...args);
|
|
1358
|
-
}
|
|
1359
|
-
hasListeners(channel) {
|
|
1360
|
-
const list = this._listeners[channel];
|
|
1361
|
-
return !!list && list.length > 0;
|
|
1362
|
-
}
|
|
1363
|
-
/** Drop every listener on every channel (used when the owning object is disposed). */
|
|
1364
|
-
clearListeners() {
|
|
1365
|
-
this._listeners = {};
|
|
1366
|
-
}
|
|
1367
|
-
};
|
|
1368
|
-
|
|
1369
1421
|
// src/runtime/net.ts
|
|
1370
1422
|
var WebSocket = class extends Emitter {
|
|
1371
1423
|
_id = null;
|
|
@@ -1585,7 +1637,7 @@ var Registry = class {
|
|
|
1585
1637
|
|
|
1586
1638
|
// src/g2/Node2D.ts
|
|
1587
1639
|
var node2dRegistry = new Registry();
|
|
1588
|
-
var Node2D = class extends
|
|
1640
|
+
var Node2D = class extends AspectHost {
|
|
1589
1641
|
/** Native entity handle. */
|
|
1590
1642
|
id;
|
|
1591
1643
|
_x = 0;
|
|
@@ -1665,17 +1717,15 @@ var Node2D = class extends Emitter {
|
|
|
1665
1717
|
this._visible = v;
|
|
1666
1718
|
_creator2d.setVisible(this.id, v);
|
|
1667
1719
|
}
|
|
1668
|
-
/**
|
|
1669
|
-
*
|
|
1670
|
-
* so this records intent and is a no-op until the engine lands — the 'enter'/'exit' events won't
|
|
1671
|
-
* fire. The API is here so game code that uses it compiles and stays stable.
|
|
1672
|
-
*/
|
|
1673
|
-
collider(_options = {}) {
|
|
1674
|
-
return this;
|
|
1675
|
-
}
|
|
1676
|
-
/** @internal — overridden by Sprite to translate native clip ids into named animation events. */
|
|
1720
|
+
/** @internal — host animation events route here by id; the SpriteAnimation aspect installs an
|
|
1721
|
+
* instance override that translates clip ids to names and emits 'loopReached' / 'completed'. */
|
|
1677
1722
|
_dispatchAnimEvent(_clipId, _type) {
|
|
1678
1723
|
}
|
|
1724
|
+
/** @internal — emit a translated animation event (the SpriteAnimation aspect can't reach the
|
|
1725
|
+
* protected dispatch directly). */
|
|
1726
|
+
_emitAnim(channel, clip) {
|
|
1727
|
+
this.dispatch(channel, clip);
|
|
1728
|
+
}
|
|
1679
1729
|
destroy() {
|
|
1680
1730
|
node2dRegistry.delete(this.id);
|
|
1681
1731
|
_creator2d.destroyEntity(this.id);
|
|
@@ -1837,9 +1887,6 @@ var Sprite = class extends Node2D {
|
|
|
1837
1887
|
_flipX = false;
|
|
1838
1888
|
_flipY = false;
|
|
1839
1889
|
_size = null;
|
|
1840
|
-
_clipIds = {};
|
|
1841
|
-
_clipNames = {};
|
|
1842
|
-
_current = null;
|
|
1843
1890
|
constructor(options = {}) {
|
|
1844
1891
|
super();
|
|
1845
1892
|
if (options.texture) this.texture = options.texture;
|
|
@@ -1913,71 +1960,94 @@ var Sprite = class extends Node2D {
|
|
|
1913
1960
|
this._flipY = v;
|
|
1914
1961
|
_creator2d.setSpriteFlip(this.id, this._flipX, v);
|
|
1915
1962
|
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1963
|
+
};
|
|
1964
|
+
|
|
1965
|
+
// src/g2/SpriteAnimation.ts
|
|
1966
|
+
var SpriteAnimation = class extends Aspect {
|
|
1967
|
+
static aspect = "anim";
|
|
1968
|
+
/** Grid cell size in texture pixels (defaults to the full texture). */
|
|
1969
|
+
size;
|
|
1970
|
+
/** Default fps for clips that don't override it. */
|
|
1971
|
+
fps = 12;
|
|
1972
|
+
/** Default loop for clips that don't override it. */
|
|
1973
|
+
loop = true;
|
|
1974
|
+
/** Named clips; frame indices are row-major into the grid. Set via the attach opts. */
|
|
1975
|
+
clips = {};
|
|
1976
|
+
_clipIds = {};
|
|
1977
|
+
_clipNames = {};
|
|
1978
|
+
_current = null;
|
|
1979
|
+
onAttach() {
|
|
1980
|
+
this._define();
|
|
1981
|
+
this.node._dispatchAnimEvent = (clipId, type) => this.node._emitAnim(type === 1 ? "completed" : "loopReached", this._clipNames[clipId] ?? "");
|
|
1982
|
+
ensureAnimEvents();
|
|
1983
|
+
}
|
|
1984
|
+
/** (Re)build native clips from `this.clips`. Called on attach; call again after changing clips. */
|
|
1985
|
+
define() {
|
|
1986
|
+
this._define();
|
|
1987
|
+
return this;
|
|
1988
|
+
}
|
|
1989
|
+
_define() {
|
|
1990
|
+
const node = this.node;
|
|
1991
|
+
const tex = node.texture;
|
|
1992
|
+
if (!tex) throw new Error("SpriteAnimation: set a texture on the Sprite before adding the aspect");
|
|
1993
|
+
const [fw, fh] = this.size ?? [tex.width, tex.height];
|
|
1927
1994
|
const cols = Math.max(1, Math.floor(tex.width / fw));
|
|
1928
|
-
for (const name of Object.keys(
|
|
1929
|
-
|
|
1930
|
-
const value = def[name];
|
|
1995
|
+
for (const name of Object.keys(this.clips)) {
|
|
1996
|
+
const value = this.clips[name];
|
|
1931
1997
|
const indices = Array.isArray(value) ? value : value.frames;
|
|
1932
|
-
const fps = Array.isArray(value) ?
|
|
1933
|
-
const loop = Array.isArray(value) ?
|
|
1998
|
+
const fps = Array.isArray(value) ? this.fps : value.fps ?? this.fps;
|
|
1999
|
+
const loop = Array.isArray(value) ? this.loop : value.loop ?? this.loop;
|
|
1934
2000
|
const frames = new Float32Array(indices.length * 4);
|
|
1935
2001
|
indices.forEach((idx, i) => {
|
|
1936
|
-
const
|
|
1937
|
-
const
|
|
1938
|
-
frames[i * 4 + 0] =
|
|
1939
|
-
frames[i * 4 + 1] =
|
|
1940
|
-
frames[i * 4 + 2] = (
|
|
1941
|
-
frames[i * 4 + 3] = (
|
|
2002
|
+
const px = idx % cols * fw;
|
|
2003
|
+
const py = Math.floor(idx / cols) * fh;
|
|
2004
|
+
frames[i * 4 + 0] = px / tex.width;
|
|
2005
|
+
frames[i * 4 + 1] = py / tex.height;
|
|
2006
|
+
frames[i * 4 + 2] = (px + fw) / tex.width;
|
|
2007
|
+
frames[i * 4 + 3] = (py + fh) / tex.height;
|
|
1942
2008
|
});
|
|
1943
|
-
const clipId = _creator2d.defineAnimation(
|
|
2009
|
+
const clipId = _creator2d.defineAnimation(node.id, frames, fps, loop);
|
|
1944
2010
|
this._clipIds[name] = clipId;
|
|
1945
2011
|
this._clipNames[clipId] = name;
|
|
1946
2012
|
}
|
|
1947
|
-
if (
|
|
1948
|
-
ensureAnimEvents();
|
|
1949
|
-
return this;
|
|
2013
|
+
if (this.size) _creator2d.setSpriteSize(node.id, fw, fh);
|
|
1950
2014
|
}
|
|
1951
2015
|
/** Play a clip by name. Re-playing the active clip is a no-op (keeps it running smoothly). */
|
|
1952
2016
|
play(name) {
|
|
1953
2017
|
const id = this._clipIds[name];
|
|
1954
|
-
if (id === void 0) throw new Error(`
|
|
2018
|
+
if (id === void 0) throw new Error(`SpriteAnimation.play(): unknown clip "${name}"`);
|
|
1955
2019
|
if (this._current === name) return this;
|
|
1956
2020
|
this._current = name;
|
|
1957
|
-
_creator2d.playAnimation(this.id, id);
|
|
2021
|
+
_creator2d.playAnimation(this.node.id, id);
|
|
1958
2022
|
return this;
|
|
1959
2023
|
}
|
|
1960
2024
|
stop() {
|
|
1961
2025
|
this._current = null;
|
|
1962
|
-
_creator2d.stopAnimation(this.id);
|
|
2026
|
+
_creator2d.stopAnimation(this.node.id);
|
|
1963
2027
|
return this;
|
|
1964
2028
|
}
|
|
1965
|
-
set
|
|
1966
|
-
_creator2d.setAnimationSpeed(this.id, value);
|
|
2029
|
+
set speed(value) {
|
|
2030
|
+
_creator2d.setAnimationSpeed(this.node.id, value);
|
|
1967
2031
|
}
|
|
1968
|
-
get
|
|
2032
|
+
get current() {
|
|
1969
2033
|
return this._current;
|
|
1970
2034
|
}
|
|
1971
|
-
get
|
|
1972
|
-
return _creator2d.getAnimationFrame(this.id);
|
|
1973
|
-
}
|
|
1974
|
-
/** @internal — translate a native clip id back to its name and emit the animation event. */
|
|
1975
|
-
_dispatchAnimEvent(clipId, type) {
|
|
1976
|
-
const name = this._clipNames[clipId] ?? "";
|
|
1977
|
-
this.dispatch(type === 1 ? "completed" : "loopReached", name);
|
|
2035
|
+
get frame() {
|
|
2036
|
+
return _creator2d.getAnimationFrame(this.node.id);
|
|
1978
2037
|
}
|
|
1979
2038
|
};
|
|
1980
2039
|
|
|
2040
|
+
// src/g2/Collider2D.ts
|
|
2041
|
+
var Collider2D = class extends Aspect {
|
|
2042
|
+
static aspect = "collider";
|
|
2043
|
+
/** Box half-extents (world units). Defaults to the sprite size when omitted. */
|
|
2044
|
+
box;
|
|
2045
|
+
/** Center offset from the node. */
|
|
2046
|
+
offset;
|
|
2047
|
+
/** Report overlaps via the node's 'enter'/'exit' events instead of blocking (always true for now). */
|
|
2048
|
+
trigger = true;
|
|
2049
|
+
};
|
|
2050
|
+
|
|
1981
2051
|
// src/g2/Tilemap.ts
|
|
1982
2052
|
var Tilemap = class extends Node2D {
|
|
1983
2053
|
cols;
|
|
@@ -3156,82 +3226,6 @@ var QRScanner = class _QRScanner {
|
|
|
3156
3226
|
}
|
|
3157
3227
|
};
|
|
3158
3228
|
|
|
3159
|
-
// src/gl/Body.ts
|
|
3160
|
-
var MOTION = { static: 0, kinematic: 1, dynamic: 2 };
|
|
3161
|
-
var Body = class {
|
|
3162
|
-
_bodyId = 0;
|
|
3163
|
-
_motion;
|
|
3164
|
-
constructor(node, options = {}) {
|
|
3165
|
-
this._motion = options.motion ?? "dynamic";
|
|
3166
|
-
const mass = options.mass ?? 1;
|
|
3167
|
-
if (!_creator.physicsHasSupport || !_creator.physicsHasSupport()) return;
|
|
3168
|
-
const motion = MOTION[this._motion];
|
|
3169
|
-
const shape = resolveShape(node, options.shape ?? { type: "auto" });
|
|
3170
|
-
if (shape.type === "sphere") {
|
|
3171
|
-
this._bodyId = _creator.physicsCreateSphere(node.id, shape.radius, motion, mass);
|
|
3172
|
-
} else if (shape.type === "cylinder") {
|
|
3173
|
-
this._bodyId = _creator.physicsCreateCylinder(node.id, shape.halfHeight, shape.radius, motion, mass);
|
|
3174
|
-
} else {
|
|
3175
|
-
this._bodyId = _creator.physicsCreateBox(node.id, cx(shape.halfExtents), cy(shape.halfExtents), cz(shape.halfExtents), motion, mass);
|
|
3176
|
-
}
|
|
3177
|
-
}
|
|
3178
|
-
/** Native Jolt body id. 0 until assigned, or if the build has no physics support. */
|
|
3179
|
-
get id() {
|
|
3180
|
-
return this._bodyId;
|
|
3181
|
-
}
|
|
3182
|
-
get motion() {
|
|
3183
|
-
return this._motion;
|
|
3184
|
-
}
|
|
3185
|
-
/** Linear velocity in world units/second (fresh Vec3 on read). */
|
|
3186
|
-
get velocity() {
|
|
3187
|
-
const out = new Float32Array(3);
|
|
3188
|
-
if (this._bodyId) _creator.physicsGetLinearVelocity(this._bodyId, out);
|
|
3189
|
-
return new Vec3(out[0], out[1], out[2]);
|
|
3190
|
-
}
|
|
3191
|
-
set velocity(v) {
|
|
3192
|
-
if (this._bodyId) _creator.physicsSetLinearVelocity(this._bodyId, cx(v), cy(v), cz(v));
|
|
3193
|
-
}
|
|
3194
|
-
/** Apply an instantaneous impulse (kg·m/s) and wake the body. */
|
|
3195
|
-
applyImpulse(v) {
|
|
3196
|
-
if (this._bodyId) _creator.physicsApplyImpulse(this._bodyId, cx(v), cy(v), cz(v));
|
|
3197
|
-
return this;
|
|
3198
|
-
}
|
|
3199
|
-
/** Teleport / drive a kinematic (or dynamic) body to a world position. */
|
|
3200
|
-
moveTo(p) {
|
|
3201
|
-
if (this._bodyId) _creator.physicsSetBodyPosition(this._bodyId, cx(p), cy(p), cz(p));
|
|
3202
|
-
return this;
|
|
3203
|
-
}
|
|
3204
|
-
/** Remove the body from the simulation. */
|
|
3205
|
-
remove() {
|
|
3206
|
-
if (this._bodyId) {
|
|
3207
|
-
_creator.physicsRemoveBody(this._bodyId);
|
|
3208
|
-
this._bodyId = 0;
|
|
3209
|
-
}
|
|
3210
|
-
}
|
|
3211
|
-
};
|
|
3212
|
-
var resolveShape = (node, shape) => {
|
|
3213
|
-
if (shape.type !== "auto") return shape;
|
|
3214
|
-
const scale = node.worldScale;
|
|
3215
|
-
let hx = 0.5, hy = 0.5, hz = 0.5;
|
|
3216
|
-
const geom = node.geometry;
|
|
3217
|
-
if (geom) {
|
|
3218
|
-
const v = geom.vertices;
|
|
3219
|
-
let minX = Infinity, minY = Infinity, minZ = Infinity, maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
|
|
3220
|
-
for (let i = 0; i + 2 < v.length; i += 3) {
|
|
3221
|
-
if (v[i] < minX) minX = v[i];
|
|
3222
|
-
if (v[i] > maxX) maxX = v[i];
|
|
3223
|
-
if (v[i + 1] < minY) minY = v[i + 1];
|
|
3224
|
-
if (v[i + 1] > maxY) maxY = v[i + 1];
|
|
3225
|
-
if (v[i + 2] < minZ) minZ = v[i + 2];
|
|
3226
|
-
if (v[i + 2] > maxZ) maxZ = v[i + 2];
|
|
3227
|
-
}
|
|
3228
|
-
hx = (maxX - minX) * 0.5;
|
|
3229
|
-
hy = (maxY - minY) * 0.5;
|
|
3230
|
-
hz = (maxZ - minZ) * 0.5;
|
|
3231
|
-
}
|
|
3232
|
-
return { type: "box", halfExtents: [hx * scale.x, hy * scale.y, hz * scale.z] };
|
|
3233
|
-
};
|
|
3234
|
-
|
|
3235
3229
|
// src/gl/state.ts
|
|
3236
3230
|
var glState = { activeScene: null };
|
|
3237
3231
|
|
|
@@ -3285,17 +3279,9 @@ var registerTouchEndEvent = () => {
|
|
|
3285
3279
|
|
|
3286
3280
|
// src/gl/Node.ts
|
|
3287
3281
|
var nodeRegistry = new Registry();
|
|
3288
|
-
var
|
|
3289
|
-
var ensureAnimator = () => {
|
|
3290
|
-
if (animatorRegistered) return;
|
|
3291
|
-
animatorRegistered = true;
|
|
3292
|
-
_creator.setOnAnimationComplete((entityId, clipIndex) => nodeRegistry.get(entityId)?._onAnimationComplete(clipIndex) ?? true);
|
|
3293
|
-
};
|
|
3294
|
-
var Node = class _Node extends Emitter {
|
|
3282
|
+
var Node = class _Node extends AspectHost {
|
|
3295
3283
|
/** Native entity handle. */
|
|
3296
3284
|
id;
|
|
3297
|
-
/** Physics handle once .physics() is called. */
|
|
3298
|
-
body;
|
|
3299
3285
|
/** AR anchors only — whether the anchor is currently being tracked. Kept in step with the
|
|
3300
3286
|
* 'track' / 'untrack' events; `false` for any non-anchor node. */
|
|
3301
3287
|
isTracked = false;
|
|
@@ -3303,10 +3289,8 @@ var Node = class _Node extends Emitter {
|
|
|
3303
3289
|
_lastSync = 0;
|
|
3304
3290
|
_worldMatrix;
|
|
3305
3291
|
_scaleCache;
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
_animSpeed = 1;
|
|
3309
|
-
_animLoop = false;
|
|
3292
|
+
/** @internal — the active animation aspect's clip-complete handler (installed by ModelAnimation). */
|
|
3293
|
+
_animComplete;
|
|
3310
3294
|
constructor(internalId) {
|
|
3311
3295
|
super();
|
|
3312
3296
|
this.id = internalId ?? _creator.createEntity();
|
|
@@ -3476,24 +3460,7 @@ var Node = class _Node extends Emitter {
|
|
|
3476
3460
|
callback(this);
|
|
3477
3461
|
_creator.traverse(this.id, (id) => callback(nodeRegistry.get(id) ?? new _Node(id)));
|
|
3478
3462
|
}
|
|
3479
|
-
// --- behaviors ---
|
|
3480
|
-
/** Add a physics body (reach it at node.body). Chainable. */
|
|
3481
|
-
physics(options = {}) {
|
|
3482
|
-
this.body = new Body(this, options);
|
|
3483
|
-
return this;
|
|
3484
|
-
}
|
|
3485
|
-
/** Add a collider for click/touch hit-testing. Derives from the mesh by default. Chainable. */
|
|
3486
|
-
collider(options = {}) {
|
|
3487
|
-
const form = options.shape ?? "box";
|
|
3488
|
-
if (form === "box" && options.center && options.size) {
|
|
3489
|
-
_creator.setColliderBox(this.id, cx(options.center), cy(options.center), cz(options.center), cx(options.size), cy(options.size), cz(options.size));
|
|
3490
|
-
} else if (form === "sphere" && options.center && options.radius !== void 0) {
|
|
3491
|
-
_creator.setColliderSphere(this.id, cx(options.center), cy(options.center), cz(options.center), options.radius);
|
|
3492
|
-
} else {
|
|
3493
|
-
_creator.setColliderFromMesh(this.id, this.id, form === "sphere" ? 1 : 0);
|
|
3494
|
-
}
|
|
3495
|
-
return this;
|
|
3496
|
-
}
|
|
3463
|
+
// --- behaviors are aspects: node.aspect(Physics, …) / node.aspect(Collider, …) ---
|
|
3497
3464
|
/** Orient the node so the given axis (default "-z", "forward") points at a world point. */
|
|
3498
3465
|
lookAt(point, mode = "-z", ortho = [0, 1, 0]) {
|
|
3499
3466
|
const world = this.worldMatrix;
|
|
@@ -3542,52 +3509,6 @@ var Node = class _Node extends Emitter {
|
|
|
3542
3509
|
);
|
|
3543
3510
|
return this;
|
|
3544
3511
|
}
|
|
3545
|
-
// --- GLB animation (no-op until a GLB is loaded as this node) ---
|
|
3546
|
-
get clips() {
|
|
3547
|
-
return _creator.getGlbAnimations(this.id);
|
|
3548
|
-
}
|
|
3549
|
-
get animationPlaying() {
|
|
3550
|
-
return this._animPlaying;
|
|
3551
|
-
}
|
|
3552
|
-
set animationPlaying(value) {
|
|
3553
|
-
this._animPlaying = value;
|
|
3554
|
-
_creator.setAnimation(this.id, value, this._animClip, this._animSpeed);
|
|
3555
|
-
}
|
|
3556
|
-
/** Play a GLB clip by name or index. Chainable. */
|
|
3557
|
-
play(clip, options = {}) {
|
|
3558
|
-
if (typeof clip === "number") this._animClip = clip;
|
|
3559
|
-
else if (typeof clip === "string") {
|
|
3560
|
-
const i = this.clips.findIndex((c2) => c2.name === clip);
|
|
3561
|
-
if (i >= 0) this._animClip = i;
|
|
3562
|
-
}
|
|
3563
|
-
if (options.loop !== void 0) this._animLoop = options.loop;
|
|
3564
|
-
this.animationPlaying = true;
|
|
3565
|
-
ensureAnimator();
|
|
3566
|
-
return this;
|
|
3567
|
-
}
|
|
3568
|
-
stop() {
|
|
3569
|
-
this.animationPlaying = false;
|
|
3570
|
-
return this;
|
|
3571
|
-
}
|
|
3572
|
-
get animationLoop() {
|
|
3573
|
-
return this._animLoop;
|
|
3574
|
-
}
|
|
3575
|
-
set animationLoop(v) {
|
|
3576
|
-
this._animLoop = v;
|
|
3577
|
-
}
|
|
3578
|
-
get animationSpeed() {
|
|
3579
|
-
return this._animSpeed;
|
|
3580
|
-
}
|
|
3581
|
-
set animationSpeed(v) {
|
|
3582
|
-
this._animSpeed = v;
|
|
3583
|
-
_creator.setAnimation(this.id, this._animPlaying, this._animClip, v);
|
|
3584
|
-
}
|
|
3585
|
-
get animationTime() {
|
|
3586
|
-
return _creator.getAnimationTime(this.id);
|
|
3587
|
-
}
|
|
3588
|
-
set animationTime(v) {
|
|
3589
|
-
_creator.setAnimationTime(this.id, this._animClip, v);
|
|
3590
|
-
}
|
|
3591
3512
|
// --- events ---
|
|
3592
3513
|
addEventListener(channel, callback) {
|
|
3593
3514
|
if (channel === "click") registerTouchEndEvent();
|
|
@@ -3598,14 +3519,14 @@ var Node = class _Node extends Emitter {
|
|
|
3598
3519
|
_dispatchEvent(channel, ...args) {
|
|
3599
3520
|
this.dispatch(channel, ...args);
|
|
3600
3521
|
}
|
|
3601
|
-
/** @internal — host animation-complete callback;
|
|
3522
|
+
/** @internal — host animation-complete callback; forwards to the ModelAnimation aspect (if any).
|
|
3523
|
+
* Returns whether the clip should keep playing. */
|
|
3602
3524
|
_onAnimationComplete(clipIndex) {
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
return this._animPlaying;
|
|
3525
|
+
return this._animComplete?.(clipIndex) ?? true;
|
|
3526
|
+
}
|
|
3527
|
+
/** @internal — emit a GLB animation event (the ModelAnimation aspect can't reach protected dispatch). */
|
|
3528
|
+
_emitAnim(channel, clip) {
|
|
3529
|
+
this.dispatch(channel, clip);
|
|
3609
3530
|
}
|
|
3610
3531
|
destroy() {
|
|
3611
3532
|
nodeRegistry.delete(this.id);
|
|
@@ -4166,10 +4087,10 @@ var createPlane = (options = {}) => {
|
|
|
4166
4087
|
let upVector, rightVec;
|
|
4167
4088
|
if (normal[1] === 0 && normal[2] === 0) {
|
|
4168
4089
|
upVector = [0, 1, 0];
|
|
4169
|
-
rightVec = [0, 0, normal[0]];
|
|
4090
|
+
rightVec = [0, 0, -normal[0]];
|
|
4170
4091
|
} else if (normal[0] === 0 && normal[2] === 0) {
|
|
4171
4092
|
upVector = [0, 0, 1];
|
|
4172
|
-
rightVec = [normal[1], 0, 0];
|
|
4093
|
+
rightVec = [-normal[1], 0, 0];
|
|
4173
4094
|
} else if (normal[0] === 0 && normal[1] === 0) {
|
|
4174
4095
|
upVector = [0, 1, 0];
|
|
4175
4096
|
rightVec = [normal[2], 0, 0];
|
|
@@ -4259,15 +4180,101 @@ var Mesh = class _Mesh extends Node {
|
|
|
4259
4180
|
static from(geometry, options = {}) {
|
|
4260
4181
|
return apply(new _Mesh(geometry, options.material), options);
|
|
4261
4182
|
}
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4183
|
+
};
|
|
4184
|
+
var sizeToVec = (s) => typeof s === "number" ? [s, s, s] : [cx(s), cy(s), cz(s)];
|
|
4185
|
+
var apply = (mesh, o) => {
|
|
4186
|
+
if (o.position) mesh.position = o.position;
|
|
4187
|
+
if (o.eulerAngles) mesh.eulerAngles = o.eulerAngles;
|
|
4188
|
+
if (o.scale !== void 0) mesh.scale = typeof o.scale === "number" ? [o.scale, o.scale, o.scale] : o.scale;
|
|
4189
|
+
if (o.name !== void 0) mesh.name = o.name;
|
|
4190
|
+
if (o.castShadows !== void 0) mesh.castShadows = o.castShadows;
|
|
4191
|
+
if (o.receiveShadows !== void 0) mesh.receiveShadows = o.receiveShadows;
|
|
4192
|
+
return mesh;
|
|
4193
|
+
};
|
|
4194
|
+
|
|
4195
|
+
// src/gl/ModelAnimation.ts
|
|
4196
|
+
var animatorRegistered = false;
|
|
4197
|
+
var ensureAnimator = () => {
|
|
4198
|
+
if (animatorRegistered) return;
|
|
4199
|
+
animatorRegistered = true;
|
|
4200
|
+
_creator.setOnAnimationComplete((entityId, clipIndex) => nodeRegistry.get(entityId)?._onAnimationComplete(clipIndex) ?? true);
|
|
4201
|
+
};
|
|
4202
|
+
var ModelAnimation = class extends Aspect {
|
|
4203
|
+
static aspect = "anim";
|
|
4204
|
+
_playing = false;
|
|
4205
|
+
_clip = 0;
|
|
4206
|
+
_speed = 1;
|
|
4207
|
+
_loop = false;
|
|
4208
|
+
onAttach() {
|
|
4209
|
+
this.node._animComplete = (clipIndex) => {
|
|
4210
|
+
if (clipIndex !== this._clip) return true;
|
|
4211
|
+
if (!this._loop) {
|
|
4212
|
+
this._playing = false;
|
|
4213
|
+
this.node._emitAnim("completed", clipIndex);
|
|
4214
|
+
} else this.node._emitAnim("loopReached", clipIndex);
|
|
4215
|
+
return this._playing;
|
|
4216
|
+
};
|
|
4217
|
+
}
|
|
4218
|
+
/** The clips baked into the glb. */
|
|
4219
|
+
get clips() {
|
|
4220
|
+
return _creator.getGlbAnimations(this.node.id);
|
|
4221
|
+
}
|
|
4222
|
+
get playing() {
|
|
4223
|
+
return this._playing;
|
|
4224
|
+
}
|
|
4225
|
+
set playing(value) {
|
|
4226
|
+
this._playing = value;
|
|
4227
|
+
_creator.setAnimation(this.node.id, value, this._clip, this._speed);
|
|
4228
|
+
}
|
|
4229
|
+
/** Play a clip by name or index. Chainable. */
|
|
4230
|
+
play(clip, options = {}) {
|
|
4231
|
+
if (typeof clip === "number") this._clip = clip;
|
|
4232
|
+
else if (typeof clip === "string") {
|
|
4233
|
+
const i = this.clips.findIndex((c2) => c2.name === clip);
|
|
4234
|
+
if (i >= 0) this._clip = i;
|
|
4235
|
+
}
|
|
4236
|
+
if (options.loop !== void 0) this._loop = options.loop;
|
|
4237
|
+
this.playing = true;
|
|
4238
|
+
ensureAnimator();
|
|
4239
|
+
return this;
|
|
4240
|
+
}
|
|
4241
|
+
stop() {
|
|
4242
|
+
this.playing = false;
|
|
4243
|
+
return this;
|
|
4244
|
+
}
|
|
4245
|
+
get loop() {
|
|
4246
|
+
return this._loop;
|
|
4247
|
+
}
|
|
4248
|
+
set loop(v) {
|
|
4249
|
+
this._loop = v;
|
|
4250
|
+
}
|
|
4251
|
+
get speed() {
|
|
4252
|
+
return this._speed;
|
|
4253
|
+
}
|
|
4254
|
+
set speed(v) {
|
|
4255
|
+
this._speed = v;
|
|
4256
|
+
_creator.setAnimation(this.node.id, this._playing, this._clip, v);
|
|
4257
|
+
}
|
|
4258
|
+
get time() {
|
|
4259
|
+
return _creator.getAnimationTime(this.node.id);
|
|
4260
|
+
}
|
|
4261
|
+
set time(v) {
|
|
4262
|
+
_creator.setAnimationTime(this.node.id, this._clip, v);
|
|
4263
|
+
}
|
|
4264
|
+
};
|
|
4265
|
+
|
|
4266
|
+
// src/gl/Model.ts
|
|
4267
|
+
var Model = class _Model extends Node {
|
|
4268
|
+
constructor(internalId) {
|
|
4269
|
+
super(internalId);
|
|
4270
|
+
this.aspect(ModelAnimation);
|
|
4271
|
+
}
|
|
4272
|
+
/** Load a GLB model. Returns its root as a Model; play its baked clips via model.anim. */
|
|
4266
4273
|
static load(source, options = {}) {
|
|
4267
4274
|
if (typeof source === "string") {
|
|
4268
4275
|
return fetch(source, { useOnce: true, onProgress: options.onProgress }).then((resp) => {
|
|
4269
4276
|
if (resp.status >= 400) return Promise.reject(new Error(`Failed to load GLB from ${source}. HTTP ${resp.status}`));
|
|
4270
|
-
return
|
|
4277
|
+
return _Model.load(resp, options);
|
|
4271
4278
|
});
|
|
4272
4279
|
}
|
|
4273
4280
|
return new Promise((resolve, reject) => {
|
|
@@ -4276,22 +4283,109 @@ var Mesh = class _Mesh extends Node {
|
|
|
4276
4283
|
reject(new Error("Failed to load GLB"));
|
|
4277
4284
|
return;
|
|
4278
4285
|
}
|
|
4279
|
-
const
|
|
4286
|
+
const model = new _Model(entityId);
|
|
4280
4287
|
if (options.culling !== true) _creator.setGlbCulling(entityId, false);
|
|
4281
|
-
resolve(
|
|
4288
|
+
resolve(model);
|
|
4282
4289
|
}, reject);
|
|
4283
4290
|
});
|
|
4284
4291
|
}
|
|
4285
4292
|
};
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4293
|
+
|
|
4294
|
+
// src/gl/Physics.ts
|
|
4295
|
+
var MOTION = { static: 0, kinematic: 1, dynamic: 2 };
|
|
4296
|
+
var Physics = class extends Aspect {
|
|
4297
|
+
static aspect = "physics";
|
|
4298
|
+
/** Default "dynamic". */
|
|
4299
|
+
motion = "dynamic";
|
|
4300
|
+
/** Mass in kg for dynamic bodies (default 1). Ignored for static/kinematic. */
|
|
4301
|
+
mass = 1;
|
|
4302
|
+
/** Default { type: "auto" } — a box from the mesh AABB × world scale. */
|
|
4303
|
+
shape = { type: "auto" };
|
|
4304
|
+
_bodyId = 0;
|
|
4305
|
+
onAttach() {
|
|
4306
|
+
if (!_creator.physicsHasSupport || !_creator.physicsHasSupport()) return;
|
|
4307
|
+
const motion = MOTION[this.motion];
|
|
4308
|
+
const shape = resolveShape(this.node, this.shape);
|
|
4309
|
+
if (shape.type === "sphere") {
|
|
4310
|
+
this._bodyId = _creator.physicsCreateSphere(this.node.id, shape.radius, motion, this.mass);
|
|
4311
|
+
} else if (shape.type === "cylinder") {
|
|
4312
|
+
this._bodyId = _creator.physicsCreateCylinder(this.node.id, shape.halfHeight, shape.radius, motion, this.mass);
|
|
4313
|
+
} else {
|
|
4314
|
+
this._bodyId = _creator.physicsCreateBox(this.node.id, cx(shape.halfExtents), cy(shape.halfExtents), cz(shape.halfExtents), motion, this.mass);
|
|
4315
|
+
}
|
|
4316
|
+
}
|
|
4317
|
+
/** Native Jolt body id. 0 until attached, or if the build has no physics support. */
|
|
4318
|
+
get id() {
|
|
4319
|
+
return this._bodyId;
|
|
4320
|
+
}
|
|
4321
|
+
/** Linear velocity in world units/second (fresh Vec3 on read). */
|
|
4322
|
+
get velocity() {
|
|
4323
|
+
const out = new Float32Array(3);
|
|
4324
|
+
if (this._bodyId) _creator.physicsGetLinearVelocity(this._bodyId, out);
|
|
4325
|
+
return new Vec3(out[0], out[1], out[2]);
|
|
4326
|
+
}
|
|
4327
|
+
set velocity(v) {
|
|
4328
|
+
if (this._bodyId) _creator.physicsSetLinearVelocity(this._bodyId, cx(v), cy(v), cz(v));
|
|
4329
|
+
}
|
|
4330
|
+
/** Apply an instantaneous impulse (kg·m/s) and wake the body. */
|
|
4331
|
+
applyImpulse(v) {
|
|
4332
|
+
if (this._bodyId) _creator.physicsApplyImpulse(this._bodyId, cx(v), cy(v), cz(v));
|
|
4333
|
+
return this;
|
|
4334
|
+
}
|
|
4335
|
+
/** Teleport / drive a kinematic (or dynamic) body to a world position. */
|
|
4336
|
+
moveTo(p) {
|
|
4337
|
+
if (this._bodyId) _creator.physicsSetBodyPosition(this._bodyId, cx(p), cy(p), cz(p));
|
|
4338
|
+
return this;
|
|
4339
|
+
}
|
|
4340
|
+
onDetach() {
|
|
4341
|
+
if (this._bodyId) {
|
|
4342
|
+
_creator.physicsRemoveBody(this._bodyId);
|
|
4343
|
+
this._bodyId = 0;
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
};
|
|
4347
|
+
var resolveShape = (node, shape) => {
|
|
4348
|
+
if (shape.type !== "auto") return shape;
|
|
4349
|
+
const scale = node.worldScale;
|
|
4350
|
+
let hx = 0.5, hy = 0.5, hz = 0.5;
|
|
4351
|
+
const geom = node.geometry;
|
|
4352
|
+
if (geom) {
|
|
4353
|
+
const v = geom.vertices;
|
|
4354
|
+
let minX = Infinity, minY = Infinity, minZ = Infinity, maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
|
|
4355
|
+
for (let i = 0; i + 2 < v.length; i += 3) {
|
|
4356
|
+
if (v[i] < minX) minX = v[i];
|
|
4357
|
+
if (v[i] > maxX) maxX = v[i];
|
|
4358
|
+
if (v[i + 1] < minY) minY = v[i + 1];
|
|
4359
|
+
if (v[i + 1] > maxY) maxY = v[i + 1];
|
|
4360
|
+
if (v[i + 2] < minZ) minZ = v[i + 2];
|
|
4361
|
+
if (v[i + 2] > maxZ) maxZ = v[i + 2];
|
|
4362
|
+
}
|
|
4363
|
+
hx = (maxX - minX) * 0.5;
|
|
4364
|
+
hy = (maxY - minY) * 0.5;
|
|
4365
|
+
hz = (maxZ - minZ) * 0.5;
|
|
4366
|
+
}
|
|
4367
|
+
return { type: "box", halfExtents: [hx * scale.x, hy * scale.y, hz * scale.z] };
|
|
4368
|
+
};
|
|
4369
|
+
|
|
4370
|
+
// src/gl/Collider.ts
|
|
4371
|
+
var Collider = class extends Aspect {
|
|
4372
|
+
static aspect = "collider";
|
|
4373
|
+
shape = "box";
|
|
4374
|
+
/** Explicit box: center + full size. */
|
|
4375
|
+
center;
|
|
4376
|
+
size;
|
|
4377
|
+
/** Explicit sphere: center + radius. */
|
|
4378
|
+
radius;
|
|
4379
|
+
onAttach() {
|
|
4380
|
+
const id = this.node.id;
|
|
4381
|
+
if (this.shape === "box" && this.center && this.size) {
|
|
4382
|
+
_creator.setColliderBox(id, cx(this.center), cy(this.center), cz(this.center), cx(this.size), cy(this.size), cz(this.size));
|
|
4383
|
+
} else if (this.shape === "sphere" && this.center && this.radius !== void 0) {
|
|
4384
|
+
_creator.setColliderSphere(id, cx(this.center), cy(this.center), cz(this.center), this.radius);
|
|
4385
|
+
} else {
|
|
4386
|
+
_creator.setColliderFromMesh(id, id, this.shape === "sphere" ? 1 : 0);
|
|
4387
|
+
}
|
|
4388
|
+
}
|
|
4295
4389
|
};
|
|
4296
4390
|
|
|
4297
4391
|
// src/gl/Light.ts
|
|
@@ -4560,9 +4654,12 @@ var dynamic = (baseValue, type, ...args) => {
|
|
|
4560
4654
|
};
|
|
4561
4655
|
export {
|
|
4562
4656
|
ARScene,
|
|
4657
|
+
Aspect,
|
|
4563
4658
|
AudioPlayer,
|
|
4564
4659
|
Camera,
|
|
4565
4660
|
ClickEvent,
|
|
4661
|
+
Collider,
|
|
4662
|
+
Collider2D,
|
|
4566
4663
|
Color,
|
|
4567
4664
|
File,
|
|
4568
4665
|
FormData,
|
|
@@ -4573,10 +4670,13 @@ export {
|
|
|
4573
4670
|
Material,
|
|
4574
4671
|
Mathf,
|
|
4575
4672
|
Mesh,
|
|
4673
|
+
Model,
|
|
4674
|
+
ModelAnimation,
|
|
4576
4675
|
Node,
|
|
4577
4676
|
Node2D,
|
|
4578
4677
|
Noise,
|
|
4579
4678
|
Particles,
|
|
4679
|
+
Physics,
|
|
4580
4680
|
Plane,
|
|
4581
4681
|
QRScanner,
|
|
4582
4682
|
Quat,
|
|
@@ -4585,6 +4685,7 @@ export {
|
|
|
4585
4685
|
Scene,
|
|
4586
4686
|
Scene2D,
|
|
4587
4687
|
Sprite,
|
|
4688
|
+
SpriteAnimation,
|
|
4588
4689
|
SvgSource,
|
|
4589
4690
|
Texture,
|
|
4590
4691
|
Texture2D,
|