spryte 0.2.3 → 0.3.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/README.md +3 -3
- package/dist/backend.d.ts +20 -3
- package/dist/backend.d.ts.map +1 -1
- package/dist/canvas2d.d.ts +10 -2
- package/dist/canvas2d.d.ts.map +1 -1
- package/dist/canvas2d.js +70 -4
- package/dist/canvas2d.js.map +1 -1
- package/dist/draw.d.ts +36 -16
- package/dist/draw.d.ts.map +1 -1
- package/dist/draw.js +25 -3
- package/dist/draw.js.map +1 -1
- package/dist/filters.d.ts +59 -0
- package/dist/filters.d.ts.map +1 -0
- package/dist/filters.js +188 -0
- package/dist/filters.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/mask.d.ts +13 -0
- package/dist/mask.d.ts.map +1 -0
- package/dist/mask.js +29 -0
- package/dist/mask.js.map +1 -0
- package/dist/offscreen.d.ts +26 -0
- package/dist/offscreen.d.ts.map +1 -0
- package/dist/offscreen.js +83 -0
- package/dist/offscreen.js.map +1 -0
- package/dist/panels.d.ts +44 -0
- package/dist/panels.d.ts.map +1 -0
- package/dist/panels.js +97 -0
- package/dist/panels.js.map +1 -0
- package/dist/renderer.js +1 -0
- package/dist/renderer.js.map +1 -1
- package/dist/shapes.d.ts +64 -0
- package/dist/shapes.d.ts.map +1 -0
- package/dist/shapes.js +367 -0
- package/dist/shapes.js.map +1 -0
- package/dist/webgl2.d.ts +8 -1
- package/dist/webgl2.d.ts.map +1 -1
- package/dist/webgl2.js +122 -6
- package/dist/webgl2.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"offscreen.js","sourceRoot":"","sources":["../src/offscreen.ts"],"names":[],"mappings":"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"}
|
package/dist/panels.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { TextureSource } from "./backend.js";
|
|
2
|
+
import type { Color } from "./color.js";
|
|
3
|
+
import type { Draw, Frame } from "./draw.js";
|
|
4
|
+
/** Options for `nineSlice` and `tiled`. */
|
|
5
|
+
export interface PanelDrawOptions {
|
|
6
|
+
/** Multiplied with the global alpha. */
|
|
7
|
+
alpha?: number;
|
|
8
|
+
/** Colour multiplier. Default white. */
|
|
9
|
+
tint?: Color;
|
|
10
|
+
/** 0..1 mix toward white. */
|
|
11
|
+
flash?: number;
|
|
12
|
+
/** Linear filtering. Default: the renderer's setting. */
|
|
13
|
+
smooth?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface TiledDrawOptions extends PanelDrawOptions {
|
|
16
|
+
/** Scroll the pattern, in source pixels before `scale` (wraps). */
|
|
17
|
+
offsetX?: number;
|
|
18
|
+
offsetY?: number;
|
|
19
|
+
/** Tile size multiplier. Default 1. */
|
|
20
|
+
scale?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Stretch a frame over a `w × h` box at `x, y` (top-left) without stretching its corners: the classic UI panel.
|
|
24
|
+
* `insets` are the corner sizes in source pixels, one number or `[left, top, right, bottom]`. Edges stretch,
|
|
25
|
+
* the centre fills, and corners shrink evenly if the box is smaller than they are. Nine quads, any backend.
|
|
26
|
+
*
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { nineSlice } from "spryte";
|
|
29
|
+
* nineSlice(draw, panel, 8, 8, 120, 48, 6);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function nineSlice(draw: Draw, frame: Frame | TextureSource, x: number, y: number, w: number, h: number, insets: number | readonly [number, number, number, number], o?: PanelDrawOptions): void;
|
|
33
|
+
/**
|
|
34
|
+
* Fill a `w × h` box at `x, y` (top-left) with a frame repeated edge to edge: scrolling backgrounds, floors,
|
|
35
|
+
* water. `offsetX/offsetY` scroll the pattern. Works on frames inside an atlas (no texture wrapping), one
|
|
36
|
+
* quad per visible tile, on any backend.
|
|
37
|
+
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { tiled } from "spryte";
|
|
40
|
+
* tiled(draw, water, 0, 120, 320, 60, { offsetX: t * 20 });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare function tiled(draw: Draw, frame: Frame | TextureSource, x: number, y: number, w: number, h: number, o?: TiledDrawOptions): void;
|
|
44
|
+
//# sourceMappingURL=panels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../src/panels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAE7C,2CAA2C;AAC3C,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB;IACxD,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,GAAG,aAAa,EAC5B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAC1D,CAAC,GAAE,gBAAuB,GACzB,IAAI,CAwBN;AAED;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CACnB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,GAAG,aAAa,EAC5B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,GAAE,gBAAuB,GACzB,IAAI,CA2BN"}
|
package/dist/panels.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const NONE = Object.freeze({});
|
|
2
|
+
/**
|
|
3
|
+
* Stretch a frame over a `w × h` box at `x, y` (top-left) without stretching its corners: the classic UI panel.
|
|
4
|
+
* `insets` are the corner sizes in source pixels, one number or `[left, top, right, bottom]`. Edges stretch,
|
|
5
|
+
* the centre fills, and corners shrink evenly if the box is smaller than they are. Nine quads, any backend.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { nineSlice } from "spryte";
|
|
9
|
+
* nineSlice(draw, panel, 8, 8, 120, 48, 6);
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export function nineSlice(draw, frame, x, y, w, h, insets, o = NONE) {
|
|
13
|
+
const f = "image" in frame ? frame : draw.wholeImage(frame);
|
|
14
|
+
const [l, t, r, b] = typeof insets === "number" ? [insets, insets, insets, insets] : insets;
|
|
15
|
+
// Corners keep their size unless they don't fit.
|
|
16
|
+
const kx = Math.min(1, w / Math.max(l + r, 1e-9));
|
|
17
|
+
const ky = Math.min(1, h / Math.max(t + b, 1e-9));
|
|
18
|
+
const xs = [x, x + l * kx, x + w - r * kx, x + w];
|
|
19
|
+
const ys = [y, y + t * ky, y + h - b * ky, y + h];
|
|
20
|
+
const us = [f.x, f.x + l, f.x + f.w - r, f.x + f.w];
|
|
21
|
+
const vs = [f.y, f.y + t, f.y + f.h - b, f.y + f.h];
|
|
22
|
+
const color = draw.spriteColor(o);
|
|
23
|
+
const smooth = o.smooth ?? draw.smooth;
|
|
24
|
+
for (let j = 0; j < 3; j++)
|
|
25
|
+
for (let i = 0; i < 3; i++) {
|
|
26
|
+
const pw = xs[i + 1] - xs[i];
|
|
27
|
+
const ph = ys[j + 1] - ys[j];
|
|
28
|
+
const sw = us[i + 1] - us[i];
|
|
29
|
+
const sh = vs[j + 1] - vs[j];
|
|
30
|
+
if (pw <= 0 || ph <= 0 || sw <= 0 || sh <= 0)
|
|
31
|
+
continue;
|
|
32
|
+
draw.local(xs[i], ys[j], pw, ph);
|
|
33
|
+
if (!smooth)
|
|
34
|
+
snapEdges(draw);
|
|
35
|
+
draw.quads++;
|
|
36
|
+
draw.backend.quad(draw.tmp, f.image, us[i], vs[j], sw, sh, color, o.flash ?? 0, smooth);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Fill a `w × h` box at `x, y` (top-left) with a frame repeated edge to edge: scrolling backgrounds, floors,
|
|
41
|
+
* water. `offsetX/offsetY` scroll the pattern. Works on frames inside an atlas (no texture wrapping), one
|
|
42
|
+
* quad per visible tile, on any backend.
|
|
43
|
+
*
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { tiled } from "spryte";
|
|
46
|
+
* tiled(draw, water, 0, 120, 320, 60, { offsetX: t * 20 });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function tiled(draw, frame, x, y, w, h, o = NONE) {
|
|
50
|
+
const f = "image" in frame ? frame : draw.wholeImage(frame);
|
|
51
|
+
const k = o.scale ?? 1;
|
|
52
|
+
const tw = f.w * k;
|
|
53
|
+
const th = f.h * k;
|
|
54
|
+
if (!(tw > 0 && th > 0 && w > 0 && h > 0))
|
|
55
|
+
return;
|
|
56
|
+
const color = draw.spriteColor(o);
|
|
57
|
+
const smooth = o.smooth ?? draw.smooth;
|
|
58
|
+
const flash = o.flash ?? 0;
|
|
59
|
+
const tiles = (Math.ceil(w / tw) + 1) * (Math.ceil(h / th) + 1);
|
|
60
|
+
if (tiles > 1_000_000)
|
|
61
|
+
throw new Error(`spryte: tiled() would draw ${tiles} tiles; use a larger frame or scale`);
|
|
62
|
+
const ox = ((((o.offsetX ?? 0) * k) % tw) + tw) % tw;
|
|
63
|
+
const oy = ((((o.offsetY ?? 0) * k) % th) + th) % th;
|
|
64
|
+
for (let ty = y - oy; ty < y + h; ty += th) {
|
|
65
|
+
const y0 = Math.max(ty, y);
|
|
66
|
+
const y1 = Math.min(ty + th, y + h);
|
|
67
|
+
if (y1 <= y0)
|
|
68
|
+
continue;
|
|
69
|
+
for (let tx = x - ox; tx < x + w; tx += tw) {
|
|
70
|
+
const x0 = Math.max(tx, x);
|
|
71
|
+
const x1 = Math.min(tx + tw, x + w);
|
|
72
|
+
if (x1 <= x0)
|
|
73
|
+
continue;
|
|
74
|
+
draw.local(x0, y0, x1 - x0, y1 - y0);
|
|
75
|
+
if (!smooth)
|
|
76
|
+
snapEdges(draw);
|
|
77
|
+
draw.quads++;
|
|
78
|
+
draw.backend.quad(draw.tmp, f.image, f.x + (x0 - tx) / k, f.y + (y0 - ty) / k, (x1 - x0) / k, (y1 - y0) / k, color, flash, smooth);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Pixel art: put an unrotated quad's edges on whole units, like `sprite()`. Neighbouring quads share edges,
|
|
84
|
+
* so they round the same way and never gap or overlap.
|
|
85
|
+
*/
|
|
86
|
+
function snapEdges(draw) {
|
|
87
|
+
const t = draw.tmp;
|
|
88
|
+
if (t[1] !== 0 || t[2] !== 0)
|
|
89
|
+
return;
|
|
90
|
+
const x0 = Math.round(t[4]);
|
|
91
|
+
const y0 = Math.round(t[5]);
|
|
92
|
+
t[0] = Math.round(t[4] + t[0]) - x0;
|
|
93
|
+
t[3] = Math.round(t[5] + t[3]) - y0;
|
|
94
|
+
t[4] = x0;
|
|
95
|
+
t[5] = y0;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=panels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panels.js","sourceRoot":"","sources":["../src/panels.ts"],"names":[],"mappings":"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"}
|
package/dist/renderer.js
CHANGED
package/dist/renderer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAe5C;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,MAAyB,EAAE,OAAO,GAAoB,EAAE;IACrF,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC;IACzC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,qGAAqG;QACrG,sGAAsG;QACtG,qFAAqF;QACrF,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE;YACrC,KAAK,EAAE,OAAO,CAAC,WAAW,IAAI,KAAK;YACnC,SAAS,EAAE,KAAK;YAChB,kBAAkB,EAAE,IAAI;YACxB,eAAe,EAAE,kBAAkB;SACpC,CAAC,CAAC;QACH,IAAI,EAAE;YAAE,OAAO,IAAI,IAAI,CAAC,IAAI,aAAa,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;QACvE,IAAI,MAAM,KAAK,QAAQ;YACrB,MAAM,IAAI,KAAK,CAAC,+FAA+F,CAAC,CAAC;IACrH,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,IAAI,KAAK,EAAE,CAAC,CAAC;IAC7E,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,sGAAsG,CAAC,CAAC;IAClI,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CACvC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,EAClD,CAAC,KAAK,EAAE,EAAE;QACR,MAAM,IAAI,KAAK,CAAC,+CAA+C,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9E,CAAC,CACF,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,OAAO,CAAC,GAA6B;IAC5C,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;IACtB,OAAO;QACL,IAAI,EAAE,IAAI;QACV,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;QACxB,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,IAAI;QACb,GAAG,EAAE,IAAI;QACT,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI;QACf,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAe5C;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,MAAyB,EAAE,OAAO,GAAoB,EAAE;IACrF,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC;IACzC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,qGAAqG;QACrG,sGAAsG;QACtG,qFAAqF;QACrF,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE;YACrC,KAAK,EAAE,OAAO,CAAC,WAAW,IAAI,KAAK;YACnC,SAAS,EAAE,KAAK;YAChB,kBAAkB,EAAE,IAAI;YACxB,eAAe,EAAE,kBAAkB;SACpC,CAAC,CAAC;QACH,IAAI,EAAE;YAAE,OAAO,IAAI,IAAI,CAAC,IAAI,aAAa,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;QACvE,IAAI,MAAM,KAAK,QAAQ;YACrB,MAAM,IAAI,KAAK,CAAC,+FAA+F,CAAC,CAAC;IACrH,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,IAAI,KAAK,EAAE,CAAC,CAAC;IAC7E,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,sGAAsG,CAAC,CAAC;IAClI,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CACvC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,EAClD,CAAC,KAAK,EAAE,EAAE;QACR,MAAM,IAAI,KAAK,CAAC,+CAA+C,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9E,CAAC,CACF,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,OAAO,CAAC,GAA6B;IAC5C,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;IACtB,OAAO;QACL,IAAI,EAAE,IAAI;QACV,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;QACxB,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,IAAI;QACb,GAAG,EAAE,IAAI;QACT,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI;QACf,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
|
package/dist/shapes.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Matrix } from "./backend.js";
|
|
2
|
+
import { type Color } from "./color.js";
|
|
3
|
+
import type { Draw } from "./draw.js";
|
|
4
|
+
/**
|
|
5
|
+
* Filled polygon through `points` (x0, y0, x1, y1, …), antialiased. Concave is fine; it closes itself and
|
|
6
|
+
* shouldn't cross itself. `count` defaults to every pair in `points`.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { polygon } from "spryte";
|
|
10
|
+
* polygon(draw, [0, 0, 20, 0, 10, 16], "#cffb2d");
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function polygon(draw: Draw, points: ArrayLike<number>, color: Color, count?: number): void;
|
|
14
|
+
/** Line through `points` (x0, y0, x1, y1, …), `width` wide, with mitred joins and flat ends. `closed` joins the last point to the first. */
|
|
15
|
+
export declare function polyline(draw: Draw, points: ArrayLike<number>, width: number, color: Color, closed?: boolean, count?: number): void;
|
|
16
|
+
/** Rectangle with rounded corners: filled, or outlined when `lineWidth` is given (the outline is centred on the edge). */
|
|
17
|
+
export declare function roundRect(draw: Draw, x: number, y: number, w: number, h: number, radius: number, color: Color, lineWidth?: number): void;
|
|
18
|
+
/** Circle outline, `width` wide, centred on `radius`. */
|
|
19
|
+
export declare function ring(draw: Draw, x: number, y: number, radius: number, width: number, color: Color): void;
|
|
20
|
+
/**
|
|
21
|
+
* Indexed triangles for the WebGL2 backend's `path()`: x, y, u, v (floats), a colour (RGBA bytes) and coverage,
|
|
22
|
+
* flash and texture unit (bytes) per vertex, 24 bytes. Sprites can join as textured quads (`sprite`). Edges get a feather one device pixel wide fading to coverage 0, which antialiases without MSAA.
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export declare class ShapeBuffer {
|
|
26
|
+
data: ArrayBuffer;
|
|
27
|
+
f32: Float32Array<ArrayBuffer>;
|
|
28
|
+
u32: Uint32Array<ArrayBuffer>;
|
|
29
|
+
indices: Uint32Array<ArrayBuffer>;
|
|
30
|
+
/** Vertices and indices written. */
|
|
31
|
+
count: number;
|
|
32
|
+
icount: number;
|
|
33
|
+
private m;
|
|
34
|
+
private color;
|
|
35
|
+
private xs;
|
|
36
|
+
private ys;
|
|
37
|
+
private nx;
|
|
38
|
+
private ny;
|
|
39
|
+
/** The inner ring of a fill, in the points' units (for ear clipping). */
|
|
40
|
+
private ix;
|
|
41
|
+
private iy;
|
|
42
|
+
/** Fill (`width` 0) or stroke `n` points. `aa` is one device pixel in the points' units; `color` is RGBA bytes in memory order. */
|
|
43
|
+
add(m: Matrix, points: ArrayLike<number>, n: number, closed: boolean, width: number, color: number, aa: number): void;
|
|
44
|
+
/** Copy points, dropping repeats; returns how many are left. Closed shapes also drop a last point equal to the first. */
|
|
45
|
+
private load;
|
|
46
|
+
/** Miter normals (left of travel) scaled so offsetting by 1 moves each edge by 1, clamped at MITER. */
|
|
47
|
+
private normals;
|
|
48
|
+
private fill;
|
|
49
|
+
private stroke;
|
|
50
|
+
/** Room for `v` more vertices and `i` more indices; returns the first new vertex's index. */
|
|
51
|
+
private reserve;
|
|
52
|
+
/** Two triangles joining edge (a, b) to edge (c, d). */
|
|
53
|
+
private quad;
|
|
54
|
+
private tri;
|
|
55
|
+
/** A textured quad: the unit square through `m`, sampling `u0, v0, u1, v1` from texture `unit`. */
|
|
56
|
+
sprite(m: Matrix, u0: number, v0: number, u1: number, v1: number, color: number, flash: number, unit: number): void;
|
|
57
|
+
private vertex;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Triangulate a simple polygon wound so its interior is on the left (positive signed area in y-down space).
|
|
61
|
+
* O(n²), fine for UI and debug shapes. Self-intersecting input still produces triangles, just not exact ones.
|
|
62
|
+
*/
|
|
63
|
+
export declare function earClip(xs: ArrayLike<number>, ys: ArrayLike<number>, n: number, tri: (a: number, b: number, c: number) => void): void;
|
|
64
|
+
//# sourceMappingURL=shapes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shapes.d.ts","sourceRoot":"","sources":["../src/shapes.ts"],"names":[],"mappings":"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"}
|
package/dist/shapes.js
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { toRGBA } from "./color.js";
|
|
2
|
+
/**
|
|
3
|
+
* Filled polygon through `points` (x0, y0, x1, y1, …), antialiased. Concave is fine; it closes itself and
|
|
4
|
+
* shouldn't cross itself. `count` defaults to every pair in `points`.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { polygon } from "spryte";
|
|
8
|
+
* polygon(draw, [0, 0, 20, 0, 10, 16], "#cffb2d");
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export function polygon(draw, points, color, count = points.length >> 1) {
|
|
12
|
+
path(draw, points, count, true, 0, color);
|
|
13
|
+
}
|
|
14
|
+
/** Line through `points` (x0, y0, x1, y1, …), `width` wide, with mitred joins and flat ends. `closed` joins the last point to the first. */
|
|
15
|
+
export function polyline(draw, points, width, color, closed = false, count = points.length >> 1) {
|
|
16
|
+
if (width > 0)
|
|
17
|
+
path(draw, points, count, closed, width, color);
|
|
18
|
+
}
|
|
19
|
+
/** Rectangle with rounded corners: filled, or outlined when `lineWidth` is given (the outline is centred on the edge). */
|
|
20
|
+
export function roundRect(draw, x, y, w, h, radius, color, lineWidth) {
|
|
21
|
+
const r = Math.max(0, Math.min(radius, w / 2, h / 2));
|
|
22
|
+
const steps = r > 0 ? arcSteps(draw, r, Math.PI / 2) : 0;
|
|
23
|
+
const pts = scratch((steps + 1) * 4);
|
|
24
|
+
let k = 0;
|
|
25
|
+
const corner = (cx, cy, from) => {
|
|
26
|
+
for (let i = 0; i <= steps; i++) {
|
|
27
|
+
const a = from + (i / Math.max(steps, 1)) * (Math.PI / 2);
|
|
28
|
+
pts[k++] = cx + Math.cos(a) * r;
|
|
29
|
+
pts[k++] = cy + Math.sin(a) * r;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
corner(x + w - r, y + r, -Math.PI / 2);
|
|
33
|
+
corner(x + w - r, y + h - r, 0);
|
|
34
|
+
corner(x + r, y + h - r, Math.PI / 2);
|
|
35
|
+
corner(x + r, y + r, Math.PI);
|
|
36
|
+
path(draw, pts, k >> 1, true, lineWidth ?? 0, color);
|
|
37
|
+
}
|
|
38
|
+
/** Circle outline, `width` wide, centred on `radius`. */
|
|
39
|
+
export function ring(draw, x, y, radius, width, color) {
|
|
40
|
+
if (radius <= 0 || width <= 0)
|
|
41
|
+
return;
|
|
42
|
+
const steps = arcSteps(draw, radius, Math.PI * 2);
|
|
43
|
+
const pts = scratch(steps * 2);
|
|
44
|
+
for (let i = 0; i < steps; i++) {
|
|
45
|
+
const a = (i / steps) * Math.PI * 2;
|
|
46
|
+
pts[i * 2] = x + Math.cos(a) * radius;
|
|
47
|
+
pts[i * 2 + 1] = y + Math.sin(a) * radius;
|
|
48
|
+
}
|
|
49
|
+
path(draw, pts, steps, true, width, color);
|
|
50
|
+
}
|
|
51
|
+
function path(draw, points, n, closed, width, color) {
|
|
52
|
+
if (n < 2)
|
|
53
|
+
return;
|
|
54
|
+
const m = draw.m;
|
|
55
|
+
// One device pixel in local units, for the WebGL2 edge feather.
|
|
56
|
+
const aa = 1 / (draw.renderScale * Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])) || 1);
|
|
57
|
+
draw.quads++;
|
|
58
|
+
draw.backend.path(m, points, n, closed, width, draw.withAlpha(toRGBA(color), 1), aa, ShapeBuffer);
|
|
59
|
+
}
|
|
60
|
+
/** Segments for an arc of `radius` spanning `angle`: about one per 4 device pixels of arc, at least 2. */
|
|
61
|
+
function arcSteps(draw, radius, angle) {
|
|
62
|
+
const m = draw.m;
|
|
63
|
+
const device = radius * Math.hypot(m[0], m[1]) * draw.renderScale;
|
|
64
|
+
return Math.max(2, Math.min(256, Math.ceil((device * angle) / 4)));
|
|
65
|
+
}
|
|
66
|
+
let points = new Float32Array(64);
|
|
67
|
+
function scratch(n) {
|
|
68
|
+
if (points.length < n)
|
|
69
|
+
points = new Float32Array(2 ** Math.ceil(Math.log2(n)));
|
|
70
|
+
return points;
|
|
71
|
+
}
|
|
72
|
+
/** Longest miter, in half line widths, before it's cut short (Canvas 2D bevels past the same limit). */
|
|
73
|
+
const MITER = 4;
|
|
74
|
+
/**
|
|
75
|
+
* Indexed triangles for the WebGL2 backend's `path()`: x, y, u, v (floats), a colour (RGBA bytes) and coverage,
|
|
76
|
+
* flash and texture unit (bytes) per vertex, 24 bytes. Sprites can join as textured quads (`sprite`). Edges get a feather one device pixel wide fading to coverage 0, which antialiases without MSAA.
|
|
77
|
+
* @internal
|
|
78
|
+
*/
|
|
79
|
+
export class ShapeBuffer {
|
|
80
|
+
data = new ArrayBuffer(1 << 16);
|
|
81
|
+
f32 = new Float32Array(this.data);
|
|
82
|
+
u32 = new Uint32Array(this.data);
|
|
83
|
+
indices = new Uint32Array(1 << 14);
|
|
84
|
+
/** Vertices and indices written. */
|
|
85
|
+
count = 0;
|
|
86
|
+
icount = 0;
|
|
87
|
+
m = [1, 0, 0, 1, 0, 0];
|
|
88
|
+
color = 0;
|
|
89
|
+
xs = new Float64Array(64);
|
|
90
|
+
ys = new Float64Array(64);
|
|
91
|
+
nx = new Float64Array(64);
|
|
92
|
+
ny = new Float64Array(64);
|
|
93
|
+
/** The inner ring of a fill, in the points' units (for ear clipping). */
|
|
94
|
+
ix = new Float64Array(64);
|
|
95
|
+
iy = new Float64Array(64);
|
|
96
|
+
/** Fill (`width` 0) or stroke `n` points. `aa` is one device pixel in the points' units; `color` is RGBA bytes in memory order. */
|
|
97
|
+
add(m, points, n, closed, width, color, aa) {
|
|
98
|
+
this.m = m;
|
|
99
|
+
this.color = color;
|
|
100
|
+
n = this.load(points, n, closed || width === 0);
|
|
101
|
+
if (width === 0)
|
|
102
|
+
this.fill(n, aa);
|
|
103
|
+
else
|
|
104
|
+
this.stroke(n, closed, width, aa);
|
|
105
|
+
}
|
|
106
|
+
/** Copy points, dropping repeats; returns how many are left. Closed shapes also drop a last point equal to the first. */
|
|
107
|
+
load(points, n, closed) {
|
|
108
|
+
if (this.xs.length < n) {
|
|
109
|
+
const size = 2 ** Math.ceil(Math.log2(n));
|
|
110
|
+
this.xs = new Float64Array(size);
|
|
111
|
+
this.ys = new Float64Array(size);
|
|
112
|
+
this.nx = new Float64Array(size);
|
|
113
|
+
this.ny = new Float64Array(size);
|
|
114
|
+
this.ix = new Float64Array(size);
|
|
115
|
+
this.iy = new Float64Array(size);
|
|
116
|
+
}
|
|
117
|
+
let k = 0;
|
|
118
|
+
for (let i = 0; i < n; i++) {
|
|
119
|
+
const x = points[i * 2];
|
|
120
|
+
const y = points[i * 2 + 1];
|
|
121
|
+
if (k > 0 && x === this.xs[k - 1] && y === this.ys[k - 1])
|
|
122
|
+
continue;
|
|
123
|
+
this.xs[k] = x;
|
|
124
|
+
this.ys[k] = y;
|
|
125
|
+
k++;
|
|
126
|
+
}
|
|
127
|
+
if (closed && k > 1 && this.xs[0] === this.xs[k - 1] && this.ys[0] === this.ys[k - 1])
|
|
128
|
+
k--;
|
|
129
|
+
return k;
|
|
130
|
+
}
|
|
131
|
+
/** Miter normals (left of travel) scaled so offsetting by 1 moves each edge by 1, clamped at MITER. */
|
|
132
|
+
normals(n, closed) {
|
|
133
|
+
const { xs, ys, nx, ny } = this;
|
|
134
|
+
for (let i = 0; i < n; i++) {
|
|
135
|
+
const p = i > 0 ? i - 1 : closed ? n - 1 : i;
|
|
136
|
+
const q = i < n - 1 ? i + 1 : closed ? 0 : i;
|
|
137
|
+
// Left normals of the edges into and out of this point.
|
|
138
|
+
let ax = ys[p] - ys[i];
|
|
139
|
+
let ay = xs[i] - xs[p];
|
|
140
|
+
let bx = ys[i] - ys[q];
|
|
141
|
+
let by = xs[q] - xs[i];
|
|
142
|
+
const la = Math.sqrt(ax * ax + ay * ay);
|
|
143
|
+
const lb = Math.sqrt(bx * bx + by * by);
|
|
144
|
+
if (la > 0) {
|
|
145
|
+
ax /= la;
|
|
146
|
+
ay /= la;
|
|
147
|
+
}
|
|
148
|
+
if (lb > 0) {
|
|
149
|
+
bx /= lb;
|
|
150
|
+
by /= lb;
|
|
151
|
+
}
|
|
152
|
+
if (la === 0) {
|
|
153
|
+
ax = bx;
|
|
154
|
+
ay = by;
|
|
155
|
+
}
|
|
156
|
+
else if (lb === 0) {
|
|
157
|
+
bx = ax;
|
|
158
|
+
by = ay;
|
|
159
|
+
}
|
|
160
|
+
let mx = ax + bx;
|
|
161
|
+
let my = ay + by;
|
|
162
|
+
const lm = Math.sqrt(mx * mx + my * my);
|
|
163
|
+
if (lm < 1e-9) {
|
|
164
|
+
mx = ax;
|
|
165
|
+
my = ay;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
mx /= lm;
|
|
169
|
+
my /= lm;
|
|
170
|
+
const s = Math.min(MITER, 1 / Math.max(mx * ax + my * ay, 1e-9));
|
|
171
|
+
mx *= s;
|
|
172
|
+
my *= s;
|
|
173
|
+
}
|
|
174
|
+
nx[i] = mx;
|
|
175
|
+
ny[i] = my;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
fill(n, aa) {
|
|
179
|
+
if (n < 3)
|
|
180
|
+
return;
|
|
181
|
+
const { xs, ys, nx, ny, ix, iy } = this;
|
|
182
|
+
// Wind one way, so left normals point inward.
|
|
183
|
+
let area = 0;
|
|
184
|
+
for (let i = 0, j = n - 1; i < n; j = i++)
|
|
185
|
+
area += xs[j] * ys[i] - xs[i] * ys[j];
|
|
186
|
+
if (area === 0)
|
|
187
|
+
return;
|
|
188
|
+
if (area < 0) {
|
|
189
|
+
xs.subarray(0, n).reverse();
|
|
190
|
+
ys.subarray(0, n).reverse();
|
|
191
|
+
}
|
|
192
|
+
this.normals(n, true);
|
|
193
|
+
const h = aa / 2;
|
|
194
|
+
const isConvex = convex(xs, ys, n);
|
|
195
|
+
// Inner ring (coverage 1) a half pixel in, then the outer ring (coverage 0) a half pixel out.
|
|
196
|
+
const base = this.reserve(2 * n, 3 * (n - 2) + 6 * n);
|
|
197
|
+
for (let i = 0; i < n; i++) {
|
|
198
|
+
ix[i] = xs[i] + nx[i] * h;
|
|
199
|
+
iy[i] = ys[i] + ny[i] * h;
|
|
200
|
+
this.vertex(ix[i], iy[i], 1);
|
|
201
|
+
}
|
|
202
|
+
for (let i = 0; i < n; i++)
|
|
203
|
+
this.vertex(xs[i] - nx[i] * h, ys[i] - ny[i] * h, 0);
|
|
204
|
+
// Convex (round rects, most UI shapes): a fan, no ear clipping.
|
|
205
|
+
if (isConvex)
|
|
206
|
+
for (let i = 1; i + 1 < n; i++)
|
|
207
|
+
this.tri(base, base + i, base + i + 1);
|
|
208
|
+
else
|
|
209
|
+
earClip(ix, iy, n, (a, b, c) => this.tri(base + a, base + b, base + c));
|
|
210
|
+
for (let i = 0; i < n; i++) {
|
|
211
|
+
const j = i === n - 1 ? 0 : i + 1;
|
|
212
|
+
this.quad(base + i, base + n + i, base + j, base + n + j);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
stroke(n, closed, width, aa) {
|
|
216
|
+
if (n < 2)
|
|
217
|
+
return;
|
|
218
|
+
if (closed && n < 3)
|
|
219
|
+
closed = false;
|
|
220
|
+
const { xs, ys, nx, ny } = this;
|
|
221
|
+
this.normals(n, closed);
|
|
222
|
+
const half = width / 2;
|
|
223
|
+
const hi = Math.max(half - aa / 2, 0);
|
|
224
|
+
const ho = half + aa / 2;
|
|
225
|
+
// Lines thinner than a pixel fade instead of shrinking below one.
|
|
226
|
+
const core = Math.min(1, width / aa);
|
|
227
|
+
const segments = closed ? n : n - 1;
|
|
228
|
+
// Four vertices per point across the line: left edge, left core, right core, right edge.
|
|
229
|
+
const base = this.reserve(4 * n, 18 * segments);
|
|
230
|
+
for (let i = 0; i < n; i++) {
|
|
231
|
+
const x = xs[i];
|
|
232
|
+
const y = ys[i];
|
|
233
|
+
const ax = nx[i];
|
|
234
|
+
const ay = ny[i];
|
|
235
|
+
this.vertex(x + ax * ho, y + ay * ho, 0);
|
|
236
|
+
this.vertex(x + ax * hi, y + ay * hi, core);
|
|
237
|
+
this.vertex(x - ax * hi, y - ay * hi, core);
|
|
238
|
+
this.vertex(x - ax * ho, y - ay * ho, 0);
|
|
239
|
+
}
|
|
240
|
+
for (let i = 0; i < segments; i++) {
|
|
241
|
+
const a = base + i * 4;
|
|
242
|
+
const b = base + (i === n - 1 ? 0 : i + 1) * 4;
|
|
243
|
+
this.quad(a, a + 1, b, b + 1);
|
|
244
|
+
this.quad(a + 1, a + 2, b + 1, b + 2);
|
|
245
|
+
this.quad(a + 2, a + 3, b + 2, b + 3);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/** Room for `v` more vertices and `i` more indices; returns the first new vertex's index. */
|
|
249
|
+
reserve(v, i) {
|
|
250
|
+
if ((this.count + v) * 24 > this.data.byteLength) {
|
|
251
|
+
const old = this.f32;
|
|
252
|
+
this.data = new ArrayBuffer(2 ** Math.ceil(Math.log2((this.count + v) * 24)));
|
|
253
|
+
this.f32 = new Float32Array(this.data);
|
|
254
|
+
this.u32 = new Uint32Array(this.data);
|
|
255
|
+
this.f32.set(old.subarray(0, this.count * 6));
|
|
256
|
+
}
|
|
257
|
+
if (this.icount + i > this.indices.length) {
|
|
258
|
+
const old = this.indices;
|
|
259
|
+
this.indices = new Uint32Array(2 ** Math.ceil(Math.log2(this.icount + i)));
|
|
260
|
+
this.indices.set(old.subarray(0, this.icount));
|
|
261
|
+
}
|
|
262
|
+
return this.count;
|
|
263
|
+
}
|
|
264
|
+
/** Two triangles joining edge (a, b) to edge (c, d). */
|
|
265
|
+
quad(a, b, c, d) {
|
|
266
|
+
this.tri(a, b, c);
|
|
267
|
+
this.tri(b, d, c);
|
|
268
|
+
}
|
|
269
|
+
tri(a, b, c) {
|
|
270
|
+
const k = this.icount;
|
|
271
|
+
this.indices[k] = a;
|
|
272
|
+
this.indices[k + 1] = b;
|
|
273
|
+
this.indices[k + 2] = c;
|
|
274
|
+
this.icount = k + 3;
|
|
275
|
+
}
|
|
276
|
+
/** A textured quad: the unit square through `m`, sampling `u0, v0, u1, v1` from texture `unit`. */
|
|
277
|
+
sprite(m, u0, v0, u1, v1, color, flash, unit) {
|
|
278
|
+
const base = this.reserve(4, 6);
|
|
279
|
+
const extra = 0xff | (Math.round(flash * 255) << 8) | (unit << 16);
|
|
280
|
+
const { f32, u32 } = this;
|
|
281
|
+
for (let c = 0; c < 4; c++) {
|
|
282
|
+
const cx = c & 1;
|
|
283
|
+
const cy = c >> 1;
|
|
284
|
+
const f = (base + c) * 6;
|
|
285
|
+
f32[f] = m[0] * cx + m[2] * cy + m[4];
|
|
286
|
+
f32[f + 1] = m[1] * cx + m[3] * cy + m[5];
|
|
287
|
+
f32[f + 2] = cx ? u1 : u0;
|
|
288
|
+
f32[f + 3] = cy ? v1 : v0;
|
|
289
|
+
u32[f + 4] = color;
|
|
290
|
+
u32[f + 5] = extra;
|
|
291
|
+
}
|
|
292
|
+
this.count += 4;
|
|
293
|
+
this.quad(base, base + 1, base + 2, base + 3);
|
|
294
|
+
}
|
|
295
|
+
vertex(x, y, coverage) {
|
|
296
|
+
const m = this.m;
|
|
297
|
+
const f = this.count * 6;
|
|
298
|
+
this.f32[f] = m[0] * x + m[2] * y + m[4];
|
|
299
|
+
this.f32[f + 1] = m[1] * x + m[3] * y + m[5];
|
|
300
|
+
this.f32[f + 2] = 0;
|
|
301
|
+
this.f32[f + 3] = 0;
|
|
302
|
+
this.u32[f + 4] = this.color;
|
|
303
|
+
// Coverage, no flash, and texture unit 255: none (the fragment stage reads white).
|
|
304
|
+
this.u32[f + 5] = Math.round(coverage * 255) | (255 << 16);
|
|
305
|
+
this.count++;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/** Every turn the same way (or straight), for a polygon wound with positive area. */
|
|
309
|
+
function convex(xs, ys, n) {
|
|
310
|
+
for (let i = 0; i < n; i++)
|
|
311
|
+
if (cross(xs, ys, i, (i + 1) % n, (i + 2) % n) < 0)
|
|
312
|
+
return false;
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
/** Reused by `earClip`, so filling shapes every frame doesn't allocate. */
|
|
316
|
+
const INDICES = [];
|
|
317
|
+
/**
|
|
318
|
+
* Triangulate a simple polygon wound so its interior is on the left (positive signed area in y-down space).
|
|
319
|
+
* O(n²), fine for UI and debug shapes. Self-intersecting input still produces triangles, just not exact ones.
|
|
320
|
+
*/
|
|
321
|
+
export function earClip(xs, ys, n, tri) {
|
|
322
|
+
const idx = INDICES;
|
|
323
|
+
idx.length = 0;
|
|
324
|
+
for (let k = 0; k < n; k++)
|
|
325
|
+
idx.push(k);
|
|
326
|
+
let guard = 0;
|
|
327
|
+
let i = 0;
|
|
328
|
+
while (idx.length > 3 && guard < idx.length) {
|
|
329
|
+
const len = idx.length;
|
|
330
|
+
const a = idx[(i + len - 1) % len];
|
|
331
|
+
const b = idx[i % len];
|
|
332
|
+
const c = idx[(i + 1) % len];
|
|
333
|
+
if (isEar(xs, ys, idx, a, b, c)) {
|
|
334
|
+
tri(a, b, c);
|
|
335
|
+
idx.splice(i % len, 1);
|
|
336
|
+
guard = 0;
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
i++;
|
|
340
|
+
guard++;
|
|
341
|
+
}
|
|
342
|
+
i %= idx.length;
|
|
343
|
+
}
|
|
344
|
+
if (idx.length === 3)
|
|
345
|
+
tri(idx[0], idx[1], idx[2]);
|
|
346
|
+
// No ear left (degenerate or self-intersecting): fan the rest.
|
|
347
|
+
else
|
|
348
|
+
for (let k = 1; k + 1 < idx.length; k++)
|
|
349
|
+
tri(idx[0], idx[k], idx[k + 1]);
|
|
350
|
+
}
|
|
351
|
+
function cross(xs, ys, a, b, c) {
|
|
352
|
+
const ax = xs[a];
|
|
353
|
+
const ay = ys[a];
|
|
354
|
+
return (xs[b] - ax) * (ys[c] - ay) - (ys[b] - ay) * (xs[c] - ax);
|
|
355
|
+
}
|
|
356
|
+
function isEar(xs, ys, idx, a, b, c) {
|
|
357
|
+
if (cross(xs, ys, a, b, c) <= 0)
|
|
358
|
+
return false;
|
|
359
|
+
for (const p of idx) {
|
|
360
|
+
if (p === a || p === b || p === c)
|
|
361
|
+
continue;
|
|
362
|
+
if (cross(xs, ys, a, b, p) >= 0 && cross(xs, ys, b, c, p) >= 0 && cross(xs, ys, c, a, p) >= 0)
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
//# sourceMappingURL=shapes.js.map
|