littlejsengine 1.19.3 → 1.21.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/FAQ.md +841 -820
- package/README.md +29 -25
- package/dist/littlejs.d.ts +2857 -955
- package/dist/littlejs.esm.js +33428 -20995
- package/dist/littlejs.esm.min.js +4 -3
- package/dist/littlejs.js +33386 -20996
- package/dist/littlejs.min.js +2 -2
- package/dist/littlejs.release.js +27841 -20422
- package/package.json +10 -5
- package/plugins/audioEffects.js +28 -24
- package/plugins/box2d.js +2516 -2073
- package/plugins/drawUtilities.js +206 -31
- package/plugins/gltf.js +786 -0
- package/plugins/jsconfig.json +19 -0
- package/plugins/lightSystem.js +719 -332
- package/plugins/math3d.js +148 -27
- package/plugins/medalSystem.js +326 -280
- package/plugins/newgrounds.js +400 -199
- package/plugins/pathFinder.js +208 -175
- package/plugins/pluginExport.js +25 -0
- package/plugins/postProcess.js +96 -24
- package/plugins/render3d.js +2067 -1632
- package/plugins/render3dDebug.js +110 -0
- package/plugins/render3dEditor.js +1812 -0
- package/plugins/render3dExtras.js +1948 -0
- package/plugins/render3dLevel.js +189 -0
- package/plugins/render3dVoxels.js +514 -0
- package/plugins/sceneSystem.js +58 -0
- package/plugins/textureSheet.js +496 -458
- package/plugins/threejs.js +183 -163
- package/plugins/tweakables.js +411 -0
- package/plugins/tweenSystem.js +265 -145
- package/plugins/uiSystem.js +2024 -1687
- package/plugins/zzfxm.js +159 -159
- package/src/engine.js +378 -97
- package/src/engineAudio.js +231 -127
- package/src/engineBuild.mjs +292 -256
- package/src/engineDebug.js +967 -743
- package/src/engineDraw.js +391 -198
- package/src/engineEditor.js +2452 -0
- package/src/engineExport.js +18 -0
- package/src/engineInput.js +1466 -1293
- package/src/engineLogo.js +19 -0
- package/src/engineMath.js +1274 -1252
- package/src/engineObject.js +197 -82
- package/src/engineParticles.js +583 -532
- package/src/engineRelease.js +79 -45
- package/src/engineSettings.js +115 -29
- package/src/engineTileLayer.js +995 -741
- package/src/engineUtilities.js +19 -13
- package/src/engineWebGL.js +239 -82
- package/src/jsconfig.json +17 -13
- package/plugins/box2d.wasm.js +0 -630
- package/plugins/box2d.wasm.wasm +0 -0
package/plugins/drawUtilities.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LittleJS Drawing Utilities Plugin
|
|
3
3
|
* - Extra drawing functions for LittleJS
|
|
4
|
-
* - Nine slice and three slice drawing
|
|
4
|
+
* - Nine slice and three slice drawing, and TileSlice to keep one as a style, like a UI skin
|
|
5
5
|
* @namespace DrawUtilities
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -9,22 +9,32 @@
|
|
|
9
9
|
|
|
10
10
|
///////////////////////////////////////////////////////////////////////////////
|
|
11
11
|
|
|
12
|
-
/** Draw a scalable nine-slice UI element
|
|
13
|
-
*
|
|
12
|
+
/** Draw a scalable nine-slice UI element in screen space, drawNineSlice with screenSpace set
|
|
13
|
+
* - Draws with the 2D context by default, on top of what WebGL drew, like drawTextScreen
|
|
14
|
+
* - With no angle its pieces land on whole pixels and meet exactly, so pixel art lines up and extraSpace is not used
|
|
14
15
|
* @param {Vector2} pos - Screen space position
|
|
15
16
|
* @param {Vector2} size - Screen space size
|
|
16
17
|
* @param {TileInfo} startTile - Top-left tile of the 3x3 block to sample (see drawNineSlice)
|
|
18
|
+
* @param {Color|number} [color=WHITE] - Color to modulate with; a number here is the borderSize of the order before 1.20, deprecated
|
|
17
19
|
* @param {number} [borderSize] - Rendered thickness of the border sections
|
|
20
|
+
* @param {Color} [additiveColor] - Additive color
|
|
18
21
|
* @param {number} [extraSpace] - Extra spacing adjustment
|
|
19
22
|
* @param {number} [angle] - Angle to rotate by
|
|
23
|
+
* @param {boolean} [useWebGL] - Use WebGL for rendering
|
|
24
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas context to use
|
|
20
25
|
* @memberof DrawUtilities */
|
|
21
|
-
function drawNineSliceScreen(pos, size, startTile, borderSize=32, extraSpace=2, angle=0)
|
|
26
|
+
function drawNineSliceScreen(pos, size, startTile, color=WHITE, borderSize=32, additiveColor, extraSpace=2, angle=0, useWebGL=false, context)
|
|
22
27
|
{
|
|
23
|
-
|
|
28
|
+
if (isNumber(color)) // deprecated since 1.20, the order before it: borderSize, extraSpace and angle after startTile
|
|
29
|
+
{
|
|
30
|
+
[borderSize, extraSpace, angle] = [/** @type {number} */ (color), arguments[4] ?? 2, arguments[5] ?? 0];
|
|
31
|
+
color = WHITE, additiveColor = undefined;
|
|
32
|
+
}
|
|
33
|
+
drawNineSlice(pos, size, startTile, /** @type {Color} */ (color), borderSize, additiveColor, extraSpace, angle, useWebGL, true, context);
|
|
24
34
|
}
|
|
25
35
|
|
|
26
36
|
/** Draw a scalable nine-slice UI element in world space
|
|
27
|
-
*
|
|
37
|
+
* Color and additive color apply in WebGL and Canvas2D (with canvasColorTiles)
|
|
28
38
|
* The nine-slice samples a 3x3 block of tiles from the tilesheet, it does not
|
|
29
39
|
* subdivide a single tile. Pass the top-left tile of that block as startTile;
|
|
30
40
|
* the other 8 tiles (edges, corners, and center) are taken automatically from
|
|
@@ -34,19 +44,37 @@ function drawNineSliceScreen(pos, size, startTile, borderSize=32, extraSpace=2,
|
|
|
34
44
|
* @param {Vector2} size - World space size
|
|
35
45
|
* @param {TileInfo} startTile - Top-left tile of the 3x3 block to sample the nine-slice from
|
|
36
46
|
* @param {Color} [color] - Color to modulate with
|
|
37
|
-
* @param {number} [borderSize] - Rendered thickness of the border sections
|
|
47
|
+
* @param {number} [borderSize] - Rendered thickness of the border sections, 1 in world space and 32 pixels in
|
|
48
|
+
* screen space by default
|
|
38
49
|
* @param {Color} [additiveColor] - Additive color
|
|
39
|
-
* @param {number} [extraSpace] - Extra spacing adjustment
|
|
50
|
+
* @param {number} [extraSpace] - Extra spacing adjustment, .05 in world space and 2 pixels in screen space by
|
|
51
|
+
* default
|
|
40
52
|
* @param {number} [angle] - Angle to rotate by
|
|
41
53
|
* @param {boolean} [useWebGL=glEnable] - Use WebGL for rendering
|
|
42
|
-
* @param {boolean} [screenSpace] - Use screen space coordinates
|
|
43
|
-
* @param {CanvasRenderingContext2D} [context] - Canvas context to use
|
|
54
|
+
* @param {boolean} [screenSpace=drawScreenSpace] - Use screen space coordinates
|
|
55
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas context to use
|
|
44
56
|
* @memberof DrawUtilities */
|
|
45
|
-
function drawNineSlice(pos, size, startTile, color, borderSize
|
|
57
|
+
function drawNineSlice(pos, size, startTile, color, borderSize, additiveColor, extraSpace, angle=0, useWebGL=glEnable, screenSpace=drawScreenSpace, context)
|
|
46
58
|
{
|
|
59
|
+
// the border and spacing defaults are in the units of the space it draws in
|
|
60
|
+
borderSize ??= screenSpace ? 32 : 1;
|
|
61
|
+
extraSpace ??= screenSpace ? 2 : .05;
|
|
62
|
+
if (!size.x || !size.y) return; // nothing to draw, the spacing must not make a sliver of it
|
|
63
|
+
if (color && color.a < 1)
|
|
64
|
+
extraSpace = 0; // see through, the overlap that hides a seam would draw twice and show brighter
|
|
47
65
|
// setup nine slice tiles - startTile is the top-left of a 3x3 tile block,
|
|
48
|
-
// so the center tile is one tile down and right from it
|
|
49
|
-
|
|
66
|
+
// so the center tile is one tile down and right from it, stepping over
|
|
67
|
+
// the padding around each tile the way tile() lays out the grid
|
|
68
|
+
const step = startTile.size.add(vec2(startTile.padding*2));
|
|
69
|
+
if (screenSpace && !angle)
|
|
70
|
+
{
|
|
71
|
+
// on whole pixels, the pieces in the screen's rows and columns of the block
|
|
72
|
+
drawSliceSnapped(pos, size, borderSize, (col, row)=>
|
|
73
|
+
[startTile.offset(step.multiply(vec2(col, row))), 0], color, additiveColor, useWebGL, context);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
borderSize = min(borderSize, abs(size.x)/2, abs(size.y)/2); // a box too small for two borders splits between them
|
|
77
|
+
const centerTile = startTile.offset(step);
|
|
50
78
|
const centerSize = size.add(vec2(extraSpace-borderSize*2));
|
|
51
79
|
const cornerSize = vec2(borderSize);
|
|
52
80
|
const cornerOffset = size.scale(.5).subtract(cornerSize.scale(.5));
|
|
@@ -61,7 +89,7 @@ function drawNineSlice(pos, size, startTile, color, borderSize=1, additiveColor,
|
|
|
61
89
|
const horizontal = i%2;
|
|
62
90
|
const sidePos = cornerOffset.multiply(vec2(horizontal?i===1?1:-1:0, horizontal?0:i?-1:1));
|
|
63
91
|
const sideSize = vec2(horizontal ? borderSize : centerSize.x, horizontal ? centerSize.y : borderSize);
|
|
64
|
-
const sideTile = centerTile.offset(
|
|
92
|
+
const sideTile = centerTile.offset(step.multiply(vec2(i===1?1:i===3?-1:0,i===0?-flip:i===2?flip:0)))
|
|
65
93
|
drawTile(pos.add(sidePos.rotate(rotateAngle)), sideSize, sideTile, color, angle, false, additiveColor, useWebGL, screenSpace, context);
|
|
66
94
|
}
|
|
67
95
|
for (let i=4; i--;)
|
|
@@ -70,27 +98,37 @@ function drawNineSlice(pos, size, startTile, color, borderSize=1, additiveColor,
|
|
|
70
98
|
const flipX = i>1;
|
|
71
99
|
const flipY = i && i<3;
|
|
72
100
|
const cornerPos = cornerOffset.multiply(vec2(flipX?-1:1, flipY?-1:1));
|
|
73
|
-
const cornerTile = centerTile.offset(
|
|
101
|
+
const cornerTile = centerTile.offset(step.multiply(vec2(flipX?-1:1,flipY?flip:-flip)));
|
|
74
102
|
drawTile(pos.add(cornerPos.rotate(rotateAngle)), cornerSize, cornerTile, color, angle, false, additiveColor, useWebGL, screenSpace, context);
|
|
75
103
|
}
|
|
76
104
|
}
|
|
77
105
|
|
|
78
|
-
/** Draw a scalable three-slice UI element
|
|
79
|
-
*
|
|
106
|
+
/** Draw a scalable three-slice UI element in screen space, drawThreeSlice with screenSpace set
|
|
107
|
+
* - Draws with the 2D context by default, on top of what WebGL drew, like drawTextScreen
|
|
108
|
+
* - With no angle its pieces land on whole pixels and meet exactly, so pixel art lines up and extraSpace is not used
|
|
80
109
|
* @param {Vector2} pos - Screen space position
|
|
81
110
|
* @param {Vector2} size - Screen space size
|
|
82
111
|
* @param {TileInfo} startTile - First of 3 consecutive tiles: corner, side, center (see drawThreeSlice)
|
|
112
|
+
* @param {Color|number} [color=WHITE] - Color to modulate with; a number here is the borderSize of the order before 1.20, deprecated
|
|
83
113
|
* @param {number} [borderSize] - Rendered thickness of the border sections
|
|
114
|
+
* @param {Color} [additiveColor] - Additive color
|
|
84
115
|
* @param {number} [extraSpace] - Extra spacing adjustment
|
|
85
116
|
* @param {number} [angle] - Angle to rotate by
|
|
117
|
+
* @param {boolean} [useWebGL] - Use WebGL for rendering
|
|
118
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas context to use
|
|
86
119
|
* @memberof DrawUtilities */
|
|
87
|
-
function drawThreeSliceScreen(pos, size, startTile, borderSize=32, extraSpace=2, angle=0)
|
|
120
|
+
function drawThreeSliceScreen(pos, size, startTile, color=WHITE, borderSize=32, additiveColor, extraSpace=2, angle=0, useWebGL=false, context)
|
|
88
121
|
{
|
|
89
|
-
|
|
122
|
+
if (isNumber(color)) // deprecated since 1.20, the order before it: borderSize, extraSpace and angle after startTile
|
|
123
|
+
{
|
|
124
|
+
[borderSize, extraSpace, angle] = [/** @type {number} */ (color), arguments[4] ?? 2, arguments[5] ?? 0];
|
|
125
|
+
color = WHITE, additiveColor = undefined;
|
|
126
|
+
}
|
|
127
|
+
drawThreeSlice(pos, size, startTile, /** @type {Color} */ (color), borderSize, additiveColor, extraSpace, angle, useWebGL, true, context);
|
|
90
128
|
}
|
|
91
129
|
|
|
92
130
|
/** Draw a scalable three-slice UI element in world space
|
|
93
|
-
*
|
|
131
|
+
* Color and additive color apply in WebGL and Canvas2D (with canvasColorTiles)
|
|
94
132
|
* The three-slice samples 3 consecutive tiles from the tilesheet, it does not
|
|
95
133
|
* subdivide a single tile. Pass the first tile as startTile; the three tiles
|
|
96
134
|
* are used in order as corner, side, and center, then rotated and mirrored to
|
|
@@ -99,20 +137,40 @@ function drawThreeSliceScreen(pos, size, startTile, borderSize=32, extraSpace=2,
|
|
|
99
137
|
* @param {Vector2} size - World space size
|
|
100
138
|
* @param {TileInfo} startTile - First of 3 consecutive tiles (corner, side, center) for the three-slice
|
|
101
139
|
* @param {Color} [color] - Color to modulate with
|
|
102
|
-
* @param {number} [borderSize] - Rendered thickness of the border sections
|
|
140
|
+
* @param {number} [borderSize] - Rendered thickness of the border sections, 1 in world space and 32 pixels in
|
|
141
|
+
* screen space by default
|
|
103
142
|
* @param {Color} [additiveColor] - Additive color
|
|
104
|
-
* @param {number} [extraSpace] - Extra spacing adjustment
|
|
143
|
+
* @param {number} [extraSpace] - Extra spacing adjustment, .05 in world space and 2 pixels in screen space by
|
|
144
|
+
* default
|
|
105
145
|
* @param {number} [angle] - Angle to rotate by
|
|
106
146
|
* @param {boolean} [useWebGL=glEnable] - Use WebGL for rendering
|
|
107
|
-
* @param {boolean} [screenSpace] - Use screen space coordinates
|
|
108
|
-
* @param {CanvasRenderingContext2D} [context] - Canvas context to use
|
|
147
|
+
* @param {boolean} [screenSpace=drawScreenSpace] - Use screen space coordinates
|
|
148
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas context to use
|
|
109
149
|
* @memberof DrawUtilities */
|
|
110
|
-
function drawThreeSlice(pos, size, startTile, color, borderSize
|
|
150
|
+
function drawThreeSlice(pos, size, startTile, color, borderSize, additiveColor, extraSpace, angle=0, useWebGL=glEnable, screenSpace=drawScreenSpace, context)
|
|
111
151
|
{
|
|
152
|
+
// the border and spacing defaults are in the units of the space it draws in
|
|
153
|
+
borderSize ??= screenSpace ? 32 : 1;
|
|
154
|
+
extraSpace ??= screenSpace ? 2 : .05;
|
|
155
|
+
if (!size.x || !size.y) return; // nothing to draw, the spacing must not make a sliver of it
|
|
156
|
+
if (color && color.a < 1)
|
|
157
|
+
extraSpace = 0; // see through, the overlap that hides a seam would draw twice and show brighter
|
|
112
158
|
// setup three slice tiles - 3 tiles in a row starting at startTile
|
|
113
159
|
const cornerTile = startTile.frame(0);
|
|
114
160
|
const sideTile = startTile.frame(1);
|
|
115
161
|
const centerTile = startTile.frame(2);
|
|
162
|
+
if (screenSpace && !angle)
|
|
163
|
+
{
|
|
164
|
+
// on whole pixels, each corner and side the top left one's tile turned a quarter more going clockwise
|
|
165
|
+
const turns = [[0,0,1],[3,-1,1],[3,2,2]]; // by column in each row, -1 for the center
|
|
166
|
+
drawSliceSnapped(pos, size, borderSize, (col, row)=>
|
|
167
|
+
{
|
|
168
|
+
const turn = turns[row][col], corner = col !== 1 && row !== 1;
|
|
169
|
+
return turn < 0 ? [centerTile, 0] : [corner ? cornerTile : sideTile, turn*PI/2];
|
|
170
|
+
}, color, additiveColor, useWebGL, context);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
borderSize = min(borderSize, abs(size.x)/2, abs(size.y)/2); // a box too small for two borders splits between them
|
|
116
174
|
const centerSize = size.add(vec2(extraSpace-borderSize*2));
|
|
117
175
|
const cornerSize = vec2(borderSize);
|
|
118
176
|
const cornerOffset = size.scale(.5).subtract(cornerSize.scale(.5));
|
|
@@ -141,21 +199,138 @@ function drawThreeSlice(pos, size, startTile, color, borderSize=1, additiveColor
|
|
|
141
199
|
}
|
|
142
200
|
}
|
|
143
201
|
|
|
202
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* A tile drawn as a box of any size, kept as a style to draw with, like a UI skin
|
|
206
|
+
* - 9 slices is a nine-slice from the 3x3 block of tiles at tileInfo, see drawNineSlice
|
|
207
|
+
* - 3 slices is a three-slice from the 3 tiles in a row at tileInfo, see drawThreeSlice
|
|
208
|
+
* - 1 slice is the whole tile stretched over the box, a plain image
|
|
209
|
+
* - The UI system draws a widget's background with one, see uiSystem.defaultSlice
|
|
210
|
+
* @memberof DrawUtilities
|
|
211
|
+
* @example
|
|
212
|
+
* const panel = new TileSlice(tile(0, 16), 9, .5); // a border of half a world unit
|
|
213
|
+
* panel.draw(vec2(0, 5), vec2(10, 4));
|
|
214
|
+
* uiSystem.defaultSlice = new TileSlice(tile(0, 16), 9, 16); // UI sizes are pixels, every widget made after this
|
|
215
|
+
*/
|
|
216
|
+
class TileSlice
|
|
217
|
+
{
|
|
218
|
+
/** Create a tile slice style
|
|
219
|
+
* @param {TileInfo} tileInfo - The tile, or the first of the tiles, to draw with
|
|
220
|
+
* @param {number} [slices] - 9 for a nine-slice, 3 for a three-slice, 1 for the whole tile
|
|
221
|
+
* @param {number} [borderSize] - Drawn thickness of the edges and corners, undefined for the draw's own default
|
|
222
|
+
* @param {number} [extraSpace] - Extra spacing adjustment of the slices, undefined for the draw's own default */
|
|
223
|
+
constructor(tileInfo, slices=9, borderSize, extraSpace)
|
|
224
|
+
{
|
|
225
|
+
ASSERT(tileInfo instanceof TileInfo, 'tileInfo must be a TileInfo');
|
|
226
|
+
ASSERT(slices === 9 || slices === 3 || slices === 1, 'slices must be 9, 3 or 1');
|
|
227
|
+
ASSERT(borderSize === undefined || isNumber(borderSize), 'borderSize must be a number');
|
|
228
|
+
|
|
229
|
+
/** @property {TileInfo} - The tile, or the first of the tiles, to draw with */
|
|
230
|
+
this.tileInfo = tileInfo;
|
|
231
|
+
/** @property {number} - 9 for a nine-slice, 3 for a three-slice, 1 for the whole tile */
|
|
232
|
+
this.slices = slices;
|
|
233
|
+
/** @property {number|undefined} - Drawn thickness of the edges and corners, undefined for the draw's default
|
|
234
|
+
* @type {number|undefined} */
|
|
235
|
+
this.borderSize = borderSize;
|
|
236
|
+
/** @property {number|undefined} - Extra spacing adjustment of the slices, undefined for the draw's default
|
|
237
|
+
* @type {number|undefined} */
|
|
238
|
+
this.extraSpace = extraSpace;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Draw it as a box in world space, or in screen space
|
|
242
|
+
* @param {Vector2} pos - Center position
|
|
243
|
+
* @param {Vector2} size - Size of the box
|
|
244
|
+
* @param {Color} [color] - Color to modulate with
|
|
245
|
+
* @param {Color} [additiveColor] - Additive color
|
|
246
|
+
* @param {number} [angle] - Angle to rotate by
|
|
247
|
+
* @param {boolean} [useWebGL=glEnable] - Use WebGL for rendering
|
|
248
|
+
* @param {boolean} [screenSpace=drawScreenSpace] - Are pos and size in screen space?
|
|
249
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas context to use */
|
|
250
|
+
draw(pos, size, color=WHITE, additiveColor, angle=0, useWebGL=glEnable, screenSpace=drawScreenSpace, context)
|
|
251
|
+
{
|
|
252
|
+
if (screenSpace) // with the screen space defaults for the border and spacing
|
|
253
|
+
return this.drawScreen(pos, size, color, additiveColor, angle, useWebGL, context);
|
|
254
|
+
if (this.slices === 9)
|
|
255
|
+
drawNineSlice(pos, size, this.tileInfo, color, this.borderSize, additiveColor, this.extraSpace, angle, useWebGL, screenSpace, context);
|
|
256
|
+
else if (this.slices === 3)
|
|
257
|
+
drawThreeSlice(pos, size, this.tileInfo, color, this.borderSize, additiveColor, this.extraSpace, angle, useWebGL, screenSpace, context);
|
|
258
|
+
else
|
|
259
|
+
drawTile(pos, size, this.tileInfo, color, angle, false, additiveColor, useWebGL, screenSpace, context);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** Draw it as a box in screen space, with the 2D context by default, on top of what WebGL drew, like drawTextScreen
|
|
263
|
+
* @param {Vector2} pos - Screen space center position
|
|
264
|
+
* @param {Vector2} size - Screen space size
|
|
265
|
+
* @param {Color} [color] - Color to modulate with
|
|
266
|
+
* @param {Color} [additiveColor] - Additive color
|
|
267
|
+
* @param {number} [angle] - Angle to rotate by
|
|
268
|
+
* @param {boolean} [useWebGL] - Use WebGL for rendering
|
|
269
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas context to use */
|
|
270
|
+
drawScreen(pos, size, color=WHITE, additiveColor, angle=0, useWebGL=false, context)
|
|
271
|
+
{
|
|
272
|
+
if (this.slices === 9)
|
|
273
|
+
drawNineSliceScreen(pos, size, this.tileInfo, color, this.borderSize, additiveColor, this.extraSpace, angle, useWebGL, context);
|
|
274
|
+
else if (this.slices === 3)
|
|
275
|
+
drawThreeSliceScreen(pos, size, this.tileInfo, color, this.borderSize, additiveColor, this.extraSpace, angle, useWebGL, context);
|
|
276
|
+
else
|
|
277
|
+
drawTile(pos, size, this.tileInfo, color, angle, false, additiveColor, useWebGL, true, context);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// draw a slice box in screen space with no angle on whole pixels: the edges and the border are rounded, and every
|
|
282
|
+
// piece is cut from them, so the pieces meet exactly and their texels line up where they do, with no overlap to hide
|
|
283
|
+
// a seam; pieceTile(col, row) gives the tile and angle for the piece in that column and row of the box, top left 0
|
|
284
|
+
function drawSliceSnapped(pos, size, borderSize, pieceTile, color, additiveColor, useWebGL, context)
|
|
285
|
+
{
|
|
286
|
+
// the pixels it lands on are the device's: a 2D context's own scale and offset, like the UI under nativeHeight
|
|
287
|
+
// centered on an odd sized canvas, or the pixel ratio; the draws land half a pixel past, see shift below
|
|
288
|
+
const canvas2D = !useWebGL || !glEnable || !!context;
|
|
289
|
+
const transform = canvas2D && (context || drawContext)?.getTransform?.();
|
|
290
|
+
const ratio = getCanvasPixelRatio();
|
|
291
|
+
const [scaleX, scaleY, offsetX, offsetY] = transform ?
|
|
292
|
+
[transform.a || 1, transform.d || 1, transform.e || 0, transform.f || 0] : [ratio, ratio, 0, 0];
|
|
293
|
+
const edges = (center, length, scale, offset)=>
|
|
294
|
+
{
|
|
295
|
+
// snapped in device order, which a mirrored context reverses, then put back in the box's own order
|
|
296
|
+
const border = max(1, round(borderSize * abs(scale)));
|
|
297
|
+
const a = round((center - length/2) * scale + offset), b = a + round(length * scale);
|
|
298
|
+
const start = min(a, b), end = max(a, b);
|
|
299
|
+
const inner = min(start + border, floor((start + end)/2)); // a box too small for two borders splits
|
|
300
|
+
const device = [start, inner, max(end - border, inner), end];
|
|
301
|
+
return (scale < 0 ? device.reverse() : device).map(edge=> (edge - offset) / scale);
|
|
302
|
+
};
|
|
303
|
+
const xs = edges(pos.x, size.x, scaleX, offsetX), ys = edges(pos.y, size.y, scaleY, offsetY);
|
|
304
|
+
const shift = .5; // a screen space draw lands half a pixel past its position, in Canvas2D and WebGL alike
|
|
305
|
+
for (let row = 3; row--;)
|
|
306
|
+
for (let col = 3; col--;)
|
|
307
|
+
{
|
|
308
|
+
const w = xs[col+1] - xs[col], h = ys[row+1] - ys[row];
|
|
309
|
+
if (w <= 0 || h <= 0) continue;
|
|
310
|
+
const [tileInfo, angle] = pieceTile(col, row);
|
|
311
|
+
const turned = round(angle / (PI/2)) % 2; // a quarter turn swaps the sides it is drawn with
|
|
312
|
+
const piecePos = vec2(xs[col] + w/2 - shift, ys[row] + h/2 - shift);
|
|
313
|
+
drawTile(piecePos, turned ? vec2(h, w) : vec2(w, h), tileInfo, color, angle, false, additiveColor, useWebGL, true, context);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
144
317
|
/** Draw a crescent / moon-phase shape built from a polygon
|
|
145
318
|
* Routes through drawPoly, so it supports WebGL, screen space, color, and outlines
|
|
319
|
+
* - At angle 0 the lit side faces up while waxing (percent below .5) and down while waning, and the lit width
|
|
320
|
+
* grows evenly with the phase, not as the real moon's does
|
|
146
321
|
* @param {Vector2} pos - Center position
|
|
147
322
|
* @param {number} [size] - Diameter
|
|
148
323
|
* @param {number} [percent] - Moon phase over a full cycle (0=new, .25=first quarter, .5=full, .75=last quarter), wraps
|
|
149
324
|
* @param {Color} [color] - Fill color
|
|
150
325
|
* @param {number} [angle] - Angle to rotate by
|
|
151
|
-
* @param {boolean} [invert] -
|
|
326
|
+
* @param {boolean} [invert] - Draw the unlit part of the disk instead of the lit part
|
|
152
327
|
* @param {number} [lineWidth] - Outline width, 0 for no outline
|
|
153
328
|
* @param {Color} [lineColor] - Outline color
|
|
154
329
|
* @param {boolean} [useWebGL=glEnable] - Use WebGL for rendering
|
|
155
|
-
* @param {boolean} [screenSpace] - Use screen space coordinates
|
|
156
|
-
* @param {CanvasRenderingContext2D} [context] - Canvas context to use
|
|
330
|
+
* @param {boolean} [screenSpace=drawScreenSpace] - Use screen space coordinates
|
|
331
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context] - Canvas context to use
|
|
157
332
|
* @memberof DrawUtilities */
|
|
158
|
-
function drawCrescent(pos, size=1, percent=0, color=WHITE, angle=0, invert=false, lineWidth=0, lineColor=BLACK, useWebGL=glEnable, screenSpace=
|
|
333
|
+
function drawCrescent(pos, size=1, percent=0, color=WHITE, angle=0, invert=false, lineWidth=0, lineColor=BLACK, useWebGL=glEnable, screenSpace=drawScreenSpace, context)
|
|
159
334
|
{
|
|
160
335
|
// build local-space points and let drawPoly apply pos/angle so screen space works
|
|
161
336
|
const points = getCrescentPoints(vec2(), size, percent, 0, invert);
|
|
@@ -168,7 +343,7 @@ function drawCrescent(pos, size=1, percent=0, color=WHITE, angle=0, invert=false
|
|
|
168
343
|
* @param {number} [size] - Diameter
|
|
169
344
|
* @param {number} [percent] - Moon phase over a full cycle (0=new, .25=first quarter, .5=full, .75=last quarter), wraps
|
|
170
345
|
* @param {number} [angle] - Angle to rotate by
|
|
171
|
-
* @param {boolean} [invert] -
|
|
346
|
+
* @param {boolean} [invert] - The unlit part of the disk instead of the lit part
|
|
172
347
|
* @param {number} [sides=glCircleSides] - Number of sides for a full circle (halved per arc)
|
|
173
348
|
* @return {Array<Vector2>} - List of points making up the crescent
|
|
174
349
|
* @memberof DrawUtilities */
|
|
@@ -182,7 +357,7 @@ function getCrescentPoints(pos, size=1, percent=0, angle=0, invert=false, sides=
|
|
|
182
357
|
if (p >= 2) // second half of cycle flips orientation
|
|
183
358
|
angle += PI;
|
|
184
359
|
p = p <= 2 ? p-1 : 3-p;
|
|
185
|
-
if (invert) //
|
|
360
|
+
if (invert) // the unlit part: the other side of the same curve
|
|
186
361
|
{
|
|
187
362
|
p = -p;
|
|
188
363
|
angle += PI;
|