@codexo/exojs 0.15.0 → 0.15.1
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/CHANGELOG.md +51 -0
- package/dist/esm/audio/Playable.d.ts +6 -1
- package/dist/esm/audio/Playable.d.ts.map +1 -1
- package/dist/esm/core/BuildInfo.js +2 -2
- package/dist/esm/core/SceneNode.d.ts +10 -1
- package/dist/esm/core/SceneNode.d.ts.map +1 -1
- package/dist/esm/core/SceneNode.js +10 -1
- package/dist/esm/core/SceneNode.js.map +1 -1
- package/dist/esm/debug/BoundingBoxesLayer.d.ts.map +1 -1
- package/dist/esm/debug/BoundingBoxesLayer.js +2 -1
- package/dist/esm/debug/BoundingBoxesLayer.js.map +1 -1
- package/dist/esm/debug/HitTestLayer.js +4 -4
- package/dist/esm/debug/HitTestLayer.js.map +1 -1
- package/dist/esm/debug/PerformanceLayer.js +1 -1
- package/dist/esm/debug/PerformanceLayer.js.map +1 -1
- package/dist/esm/debug/RenderPassInspectorLayer.js +2 -2
- package/dist/esm/debug/RenderPassInspectorLayer.js.map +1 -1
- package/dist/esm/math/AbstractVector.d.ts +4 -3
- package/dist/esm/math/AbstractVector.d.ts.map +1 -1
- package/dist/esm/math/AbstractVector.js +5 -4
- package/dist/esm/math/AbstractVector.js.map +1 -1
- package/dist/esm/math/ObservableVector.d.ts +2 -0
- package/dist/esm/math/ObservableVector.d.ts.map +1 -1
- package/dist/esm/math/ObservableVector.js +9 -0
- package/dist/esm/math/ObservableVector.js.map +1 -1
- package/dist/esm/math/Polygon.d.ts.map +1 -1
- package/dist/esm/math/Polygon.js +4 -1
- package/dist/esm/math/Polygon.js.map +1 -1
- package/dist/esm/math/collision-detection.d.ts.map +1 -1
- package/dist/esm/math/collision-detection.js +13 -13
- package/dist/esm/math/collision-detection.js.map +1 -1
- package/dist/esm/math/collision-primitives.d.ts +1 -1
- package/dist/esm/math/collision-primitives.d.ts.map +1 -1
- package/dist/esm/math/collision-primitives.js +4 -1
- package/dist/esm/math/collision-primitives.js.map +1 -1
- package/dist/esm/rendering/primitives/Graphics.d.ts +7 -0
- package/dist/esm/rendering/primitives/Graphics.d.ts.map +1 -1
- package/dist/esm/rendering/primitives/Graphics.js +20 -6
- package/dist/esm/rendering/primitives/Graphics.js.map +1 -1
- package/dist/esm/rendering/sprite/AnimatedSprite.d.ts +1 -0
- package/dist/esm/rendering/sprite/AnimatedSprite.d.ts.map +1 -1
- package/dist/esm/rendering/sprite/AnimatedSprite.js +18 -1
- package/dist/esm/rendering/sprite/AnimatedSprite.js.map +1 -1
- package/dist/esm/rendering/sprite/Sprite.d.ts.map +1 -1
- package/dist/esm/rendering/sprite/Sprite.js +8 -0
- package/dist/esm/rendering/sprite/Sprite.js.map +1 -1
- package/dist/esm/rendering/text/TextLayout.d.ts.map +1 -1
- package/dist/esm/rendering/text/TextLayout.js +2 -3
- package/dist/esm/rendering/text/TextLayout.js.map +1 -1
- package/dist/esm/resources/coreAssetBindings.d.ts +11 -0
- package/dist/esm/resources/coreAssetBindings.d.ts.map +1 -1
- package/dist/esm/resources/coreAssetBindings.js +10 -2
- package/dist/esm/resources/coreAssetBindings.js.map +1 -1
- package/dist/exo.debug.esm.js +1 -1
- package/dist/exo.debug.esm.js.map +1 -1
- package/dist/exo.esm.js +1 -1
- package/dist/exo.esm.js.map +1 -1
- package/dist/exo.iife.js +104 -33
- package/dist/exo.iife.js.map +1 -1
- package/dist/exo.iife.min.js +1 -1
- package/dist/exo.iife.min.js.map +1 -1
- package/package.json +1 -1
package/dist/exo.iife.js
CHANGED
|
@@ -1769,12 +1769,13 @@ var Exo = (function (exports) {
|
|
|
1769
1769
|
*/
|
|
1770
1770
|
class AbstractVector {
|
|
1771
1771
|
/**
|
|
1772
|
-
* Angle of this vector in radians, measured from the positive
|
|
1773
|
-
* (
|
|
1774
|
-
* preserving its {@link length}. Mutates in
|
|
1772
|
+
* Angle of this vector in radians, measured from the positive X-axis
|
|
1773
|
+
* (the same convention as `PolarVector.phi`). Setting this rotates the
|
|
1774
|
+
* vector to the new angle while preserving its {@link length}. Mutates in
|
|
1775
|
+
* place.
|
|
1775
1776
|
*/
|
|
1776
1777
|
get angle() {
|
|
1777
|
-
return Math.atan2(this.
|
|
1778
|
+
return Math.atan2(this.y, this.x);
|
|
1778
1779
|
}
|
|
1779
1780
|
set angle(angle) {
|
|
1780
1781
|
const length = this.length;
|
|
@@ -2089,7 +2090,10 @@ var Exo = (function (exports) {
|
|
|
2089
2090
|
const normY = (y1 - y2) / ry;
|
|
2090
2091
|
return normX * normX + normY * normY <= 1;
|
|
2091
2092
|
};
|
|
2092
|
-
const intersectionPointPoly$1 = (point, { points }) =>
|
|
2093
|
+
const intersectionPointPoly$1 = (point, { x: offsetX, y: offsetY, points }) =>
|
|
2094
|
+
// Shift the point into the polygon's local space so its x/y position
|
|
2095
|
+
// offset is honoured (the local `points` never carry the offset).
|
|
2096
|
+
polygonContainsPoint({ x: point.x - offsetX, y: point.y - offsetY }, points);
|
|
2093
2097
|
const intersectionLineLineSegments = (a1, a2, b1, b2) => {
|
|
2094
2098
|
const denominator = (a2.x - a1.x) * (b2.y - b1.y) - (b2.x - b1.x) * (a2.y - a1.y);
|
|
2095
2099
|
if (Math.abs(denominator) <= epsilon$1) {
|
|
@@ -2317,8 +2321,13 @@ var Exo = (function (exports) {
|
|
|
2317
2321
|
if (getVoronoiRegion(edgeX, edgeY, pointX, pointY) !== VoronoiRegion.right) {
|
|
2318
2322
|
return false;
|
|
2319
2323
|
}
|
|
2320
|
-
|
|
2321
|
-
|
|
2324
|
+
// In the right region the closest polygon feature is the *next* vertex, so
|
|
2325
|
+
// both the region refinement and the distance test use `circle - nextPoint`
|
|
2326
|
+
// (mirrors the right-region branch of getCollisionPolygonCircle).
|
|
2327
|
+
const positionBx = circleX - nextPoint.x;
|
|
2328
|
+
const positionBy = circleY - nextPoint.y;
|
|
2329
|
+
const region = getVoronoiRegion(nextEdge.x, nextEdge.y, positionBx, positionBy);
|
|
2330
|
+
return region === VoronoiRegion.left && getVectorLength(positionBx, positionBy) > radius;
|
|
2322
2331
|
};
|
|
2323
2332
|
const shouldExcludeMiddleVoronoi = (pointX, pointY, radius, edgeX, edgeY) => {
|
|
2324
2333
|
const normalX = edgeY;
|
|
@@ -2331,15 +2340,10 @@ var Exo = (function (exports) {
|
|
|
2331
2340
|
return distance > 0 && Math.abs(distance) > radius;
|
|
2332
2341
|
};
|
|
2333
2342
|
const intersectionCirclePoly = ({ x: cx, y: cy, radius }, { x: px, y: py, points, edges }) => {
|
|
2334
|
-
// Frame transform:
|
|
2335
|
-
//
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
// below combine them with the negated-offset circle position to reach the
|
|
2339
|
-
// same value as a positively-offset frame would. Don't flip without
|
|
2340
|
-
// re-deriving the Voronoi math.
|
|
2341
|
-
const circleX = px - cx;
|
|
2342
|
-
const circleY = py - cy;
|
|
2343
|
+
// Frame transform: the circle centre expressed in the polygon's local space
|
|
2344
|
+
// (circle.position - poly.position), matching getCollisionPolygonCircle.
|
|
2345
|
+
const circleX = cx - px;
|
|
2346
|
+
const circleY = cy - py;
|
|
2343
2347
|
const len = points.length;
|
|
2344
2348
|
for (let i = 0; i < len; i++) {
|
|
2345
2349
|
// i, prev, next are all valid indices into the parallel length-`len`
|
|
@@ -2428,8 +2432,8 @@ var Exo = (function (exports) {
|
|
|
2428
2432
|
difference.destroy();
|
|
2429
2433
|
return null;
|
|
2430
2434
|
}
|
|
2431
|
-
const projectionN = difference.
|
|
2432
|
-
const projectionV =
|
|
2435
|
+
const projectionN = difference.normalize();
|
|
2436
|
+
const projectionV = projectionN.clone().multiply(overlap);
|
|
2433
2437
|
return {
|
|
2434
2438
|
shapeA: circleA,
|
|
2435
2439
|
shapeB: circleB,
|
|
@@ -2942,10 +2946,19 @@ var Exo = (function (exports) {
|
|
|
2942
2946
|
this._owner?._onObservableChange(this._channel);
|
|
2943
2947
|
}
|
|
2944
2948
|
}
|
|
2949
|
+
// The getters must be redeclared alongside the setter overrides: a
|
|
2950
|
+
// setter-only accessor on the subclass prototype would shadow the whole
|
|
2951
|
+
// inherited accessor pair, leaving `get` undefined.
|
|
2952
|
+
get angle() {
|
|
2953
|
+
return Math.atan2(this._y, this._x);
|
|
2954
|
+
}
|
|
2945
2955
|
set angle(angle) {
|
|
2946
2956
|
const length = this.length;
|
|
2947
2957
|
this.set(Math.cos(angle) * length, Math.sin(angle) * length);
|
|
2948
2958
|
}
|
|
2959
|
+
get length() {
|
|
2960
|
+
return Math.sqrt(this._x * this._x + this._y * this._y);
|
|
2961
|
+
}
|
|
2949
2962
|
set length(magnitude) {
|
|
2950
2963
|
const angle = this.angle;
|
|
2951
2964
|
this.set(Math.cos(angle) * magnitude, Math.sin(angle) * magnitude);
|
|
@@ -6607,6 +6620,9 @@ var Exo = (function (exports) {
|
|
|
6607
6620
|
const length = Math.sqrt(axis.x * axis.x + axis.y * axis.y) || 1;
|
|
6608
6621
|
const nx = axis.x / length;
|
|
6609
6622
|
const ny = axis.y / length;
|
|
6623
|
+
// World-space projection: the polygon's x/y offset shifts every vertex by
|
|
6624
|
+
// the same amount, so it contributes a constant term along the axis.
|
|
6625
|
+
const offset = nx * this._position.x + ny * this._position.y;
|
|
6610
6626
|
const points = this._points;
|
|
6611
6627
|
let min = Infinity;
|
|
6612
6628
|
let max = -Infinity;
|
|
@@ -6619,7 +6635,7 @@ var Exo = (function (exports) {
|
|
|
6619
6635
|
if (projection > max)
|
|
6620
6636
|
max = projection;
|
|
6621
6637
|
}
|
|
6622
|
-
return result.set(min, max);
|
|
6638
|
+
return result.set(min + offset, max + offset);
|
|
6623
6639
|
}
|
|
6624
6640
|
contains(x, y) {
|
|
6625
6641
|
return intersectionPointPoly(Vector.temp.set(x, y), this);
|
|
@@ -7289,9 +7305,18 @@ var Exo = (function (exports) {
|
|
|
7289
7305
|
this._invalidateSubtreeTransform();
|
|
7290
7306
|
this._invalidateBoundsCascade();
|
|
7291
7307
|
}
|
|
7308
|
+
/**
|
|
7309
|
+
* Re-derive `origin` from the fractional anchor and the CURRENT local
|
|
7310
|
+
* bounds. Uses local (untransformed) bounds on purpose: the transform
|
|
7311
|
+
* multiplies the origin by scale itself, so deriving from world bounds
|
|
7312
|
+
* would double-apply scale whenever the anchor is set after scaling.
|
|
7313
|
+
* Subclasses whose local bounds change after construction (e.g. a sprite
|
|
7314
|
+
* switching to a texture sub-frame) must call this to keep an anchored
|
|
7315
|
+
* node anchored.
|
|
7316
|
+
*/
|
|
7292
7317
|
_updateOrigin() {
|
|
7293
7318
|
const { x, y } = this._anchor;
|
|
7294
|
-
const { width, height } = this.
|
|
7319
|
+
const { width, height } = this.getLocalBounds();
|
|
7295
7320
|
this.setOrigin(width * x, height * y);
|
|
7296
7321
|
}
|
|
7297
7322
|
}
|
|
@@ -16342,6 +16367,14 @@ var Exo = (function (exports) {
|
|
|
16342
16367
|
this.width = width;
|
|
16343
16368
|
this.height = height;
|
|
16344
16369
|
}
|
|
16370
|
+
// The local bounds changed size — re-derive the origin from the
|
|
16371
|
+
// fractional anchor, or an anchored sprite keeps the OLD bounds' pixel
|
|
16372
|
+
// origin and renders offset by the size difference (an anchored sprite
|
|
16373
|
+
// switching from the full atlas to its first animation frame used to
|
|
16374
|
+
// land hundreds of pixels off-canvas).
|
|
16375
|
+
if (this.anchor.x !== 0 || this.anchor.y !== 0) {
|
|
16376
|
+
this._updateOrigin();
|
|
16377
|
+
}
|
|
16345
16378
|
this.invalidateCache();
|
|
16346
16379
|
return this;
|
|
16347
16380
|
}
|
|
@@ -16618,13 +16651,12 @@ var Exo = (function (exports) {
|
|
|
16618
16651
|
const extraPerGap = (maxLineWidth - line.width) / gaps;
|
|
16619
16652
|
let wordIdx = -1;
|
|
16620
16653
|
let prevWasSpace = true;
|
|
16621
|
-
const spaceAdv = provider.getGlyph(' ', fontSize).advance;
|
|
16622
16654
|
for (const entry of line.placements) {
|
|
16623
|
-
if (prevWasSpace && entry.
|
|
16655
|
+
if (prevWasSpace && entry.char !== ' ') {
|
|
16624
16656
|
wordIdx++;
|
|
16625
16657
|
prevWasSpace = false;
|
|
16626
16658
|
}
|
|
16627
|
-
else if (!prevWasSpace && entry.
|
|
16659
|
+
else if (!prevWasSpace && entry.char === ' ') {
|
|
16628
16660
|
prevWasSpace = true;
|
|
16629
16661
|
}
|
|
16630
16662
|
result.push({
|
|
@@ -33408,14 +33440,22 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33408
33440
|
* parent's source. `new URL(ref, source)` only works when `source` is an
|
|
33409
33441
|
* absolute URL; loaders are frequently called with relative paths (e.g.
|
|
33410
33442
|
* `assets/demo/fonts/x.fnt`), so fall back to a synthetic base and strip it.
|
|
33443
|
+
* A root-absolute source (`/assets/demo/fonts/x.fnt`) must yield a
|
|
33444
|
+
* root-absolute result again — dropping the leading slash would make the
|
|
33445
|
+
* browser re-resolve the page image against the document base URL.
|
|
33446
|
+
* @internal exported for tests
|
|
33411
33447
|
*/
|
|
33412
33448
|
function resolveSubAssetPath(ref, source) {
|
|
33449
|
+
if (/^(?:[a-z][a-z\d+.-]*:|\/\/|\/)/i.test(ref)) {
|
|
33450
|
+
return ref;
|
|
33451
|
+
}
|
|
33413
33452
|
try {
|
|
33414
33453
|
return new URL(ref, source).href;
|
|
33415
33454
|
}
|
|
33416
33455
|
catch {
|
|
33417
33456
|
const base = 'https://exojs.invalid/';
|
|
33418
|
-
|
|
33457
|
+
const resolved = new URL(ref, base + source.replace(/^\/+/, '')).href.slice(base.length);
|
|
33458
|
+
return source.startsWith('/') ? `/${resolved}` : resolved;
|
|
33419
33459
|
}
|
|
33420
33460
|
}
|
|
33421
33461
|
// ---------------------------------------------------------------------------
|
|
@@ -36661,12 +36701,26 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
36661
36701
|
this.addChild(this._createStrokeMesh(data));
|
|
36662
36702
|
return this;
|
|
36663
36703
|
}
|
|
36704
|
+
/**
|
|
36705
|
+
* Stroke a shape's perimeter. Shape builders return their outline OPEN
|
|
36706
|
+
* (first point not repeated), but `buildPath` only closes a path whose
|
|
36707
|
+
* first and last points coincide — so the closing segment (e.g. a
|
|
36708
|
+
* rectangle's left edge) went missing. Repeat the first point here.
|
|
36709
|
+
*/
|
|
36710
|
+
_strokeClosedOutline(points) {
|
|
36711
|
+
if (points.length >= 4) {
|
|
36712
|
+
this.drawPath([...points, points[0], points[1]]);
|
|
36713
|
+
}
|
|
36714
|
+
else {
|
|
36715
|
+
this.drawPath(points);
|
|
36716
|
+
}
|
|
36717
|
+
}
|
|
36664
36718
|
/** Fill a closed polygon defined by `[x0,y0, x1,y1, ...]` and optionally stroke its outline. */
|
|
36665
36719
|
drawPolygon(path) {
|
|
36666
36720
|
const data = buildPolygon(path);
|
|
36667
36721
|
this._appendFill(data);
|
|
36668
36722
|
if (this._lineWidth > 0) {
|
|
36669
|
-
this.
|
|
36723
|
+
this._strokeClosedOutline(data.points);
|
|
36670
36724
|
}
|
|
36671
36725
|
return this;
|
|
36672
36726
|
}
|
|
@@ -36675,7 +36729,7 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
36675
36729
|
const data = buildCircle(centerX, centerY, radius);
|
|
36676
36730
|
this._appendFill(data);
|
|
36677
36731
|
if (this._lineWidth > 0) {
|
|
36678
|
-
this.
|
|
36732
|
+
this._strokeClosedOutline(data.points);
|
|
36679
36733
|
}
|
|
36680
36734
|
return this;
|
|
36681
36735
|
}
|
|
@@ -36684,7 +36738,7 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
36684
36738
|
const data = buildEllipse(centerX, centerY, radiusX, radiusY);
|
|
36685
36739
|
this._appendFill(data);
|
|
36686
36740
|
if (this._lineWidth > 0) {
|
|
36687
|
-
this.
|
|
36741
|
+
this._strokeClosedOutline(data.points);
|
|
36688
36742
|
}
|
|
36689
36743
|
return this;
|
|
36690
36744
|
}
|
|
@@ -36693,7 +36747,7 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
36693
36747
|
const data = buildRectangle(x, y, width, height);
|
|
36694
36748
|
this._appendFill(data);
|
|
36695
36749
|
if (this._lineWidth > 0) {
|
|
36696
|
-
this.
|
|
36750
|
+
this._strokeClosedOutline(data.points);
|
|
36697
36751
|
}
|
|
36698
36752
|
return this;
|
|
36699
36753
|
}
|
|
@@ -36706,7 +36760,7 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
36706
36760
|
const data = buildRoundedRectangle(x, y, width, height, radius);
|
|
36707
36761
|
this._appendFill(data);
|
|
36708
36762
|
if (this._lineWidth > 0) {
|
|
36709
|
-
this.
|
|
36763
|
+
this._strokeClosedOutline(data.points);
|
|
36710
36764
|
}
|
|
36711
36765
|
return this;
|
|
36712
36766
|
}
|
|
@@ -36718,7 +36772,7 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
36718
36772
|
const data = buildStar(centerX, centerY, points, radius, innerRadius, rotation);
|
|
36719
36773
|
this._appendFill(data);
|
|
36720
36774
|
if (this._lineWidth > 0) {
|
|
36721
|
-
this.
|
|
36775
|
+
this._strokeClosedOutline(data.points);
|
|
36722
36776
|
}
|
|
36723
36777
|
return this;
|
|
36724
36778
|
}
|
|
@@ -36885,6 +36939,7 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
36885
36939
|
_clips = new Map();
|
|
36886
36940
|
_currentClipName = null;
|
|
36887
36941
|
_currentFrameIndex = 0;
|
|
36942
|
+
_hasAppliedFrame = false;
|
|
36888
36943
|
_playing = false;
|
|
36889
36944
|
_repeatOverride = null;
|
|
36890
36945
|
_elapsedFrameTimeMs = 0;
|
|
@@ -37165,7 +37220,23 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
37165
37220
|
*/
|
|
37166
37221
|
_applyFrame(clip, frameIndex) {
|
|
37167
37222
|
// In-bounds by every call site's own guard.
|
|
37168
|
-
this.
|
|
37223
|
+
if (this._hasAppliedFrame) {
|
|
37224
|
+
// Frame-to-frame advance: keep the current pixel size so differently
|
|
37225
|
+
// sized frames don't visibly pop.
|
|
37226
|
+
this.setTextureFrame(clip.frames[frameIndex], false);
|
|
37227
|
+
}
|
|
37228
|
+
else {
|
|
37229
|
+
// First application: the sprite still shows the full source texture
|
|
37230
|
+
// (usually the whole atlas), so "keep the pixel size" would inflate the
|
|
37231
|
+
// scale by atlasSize/frameSize and the sprite would render blown up far
|
|
37232
|
+
// beyond the canvas. Snap the logical size to the frame instead — while
|
|
37233
|
+
// preserving the user's scale, which `resetSize` would reset to 1.
|
|
37234
|
+
const scaleX = this.scale.x;
|
|
37235
|
+
const scaleY = this.scale.y;
|
|
37236
|
+
this.setTextureFrame(clip.frames[frameIndex], true);
|
|
37237
|
+
this.scale.set(scaleX, scaleY);
|
|
37238
|
+
this._hasAppliedFrame = true;
|
|
37239
|
+
}
|
|
37169
37240
|
const offset = clip.frameOffsets?.[frameIndex];
|
|
37170
37241
|
if (offset) {
|
|
37171
37242
|
this.getLocalBounds().setPosition(offset.x, offset.y);
|
|
@@ -40139,8 +40210,8 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
40139
40210
|
}
|
|
40140
40211
|
|
|
40141
40212
|
const buildInfo = Object.freeze({
|
|
40142
|
-
version: "0.15.
|
|
40143
|
-
revision: "
|
|
40213
|
+
version: "0.15.1",
|
|
40214
|
+
revision: "6f825a8",
|
|
40144
40215
|
development: false,
|
|
40145
40216
|
});
|
|
40146
40217
|
|