littlejsengine 1.15.2 → 1.15.3
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/littlejs.d.ts +32 -9
- package/dist/littlejs.esm.js +128 -62
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +128 -62
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +92 -40
- package/examples/electron/index.html +2 -2
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/box2dCar.js +1 -1
- package/examples/shorts/music.js +1 -0
- package/examples/shorts/musicPlayer.js +1 -0
- package/examples/shorts/sequencer.js +2 -0
- package/examples/shorts/sound.js +1 -0
- package/examples/shorts/timers.js +1 -0
- package/examples/shorts/uiSystem.js +1 -0
- package/examples/shorts/videoPlayer.js +2 -1
- package/examples/starter/index.html +2 -2
- package/examples/uiSystem/game.js +1 -0
- package/package.json +1 -1
- package/plugins/uiSystem.js +30 -3
- package/src/engine.js +1 -1
- package/src/engineAudio.js +0 -1
- package/src/engineDebug.js +36 -22
- package/src/engineDraw.js +56 -32
- package/src/engineInput.js +1 -1
- package/src/engineObject.js +3 -1
- package/src/engineTileLayer.js +1 -1
package/dist/littlejs.d.ts
CHANGED
|
@@ -216,8 +216,9 @@ declare module "littlejsengine" {
|
|
|
216
216
|
* @param {number} [time]
|
|
217
217
|
* @param {number} [angle]
|
|
218
218
|
* @param {boolean} [fill]
|
|
219
|
+
* @param {boolean} [screenSpace]
|
|
219
220
|
* @memberof Debug */
|
|
220
|
-
export function debugRect(pos: Vector2, size?: Vector2, color?: Color | string, time?: number, angle?: number, fill?: boolean): void;
|
|
221
|
+
export function debugRect(pos: Vector2, size?: Vector2, color?: Color | string, time?: number, angle?: number, fill?: boolean, screenSpace?: boolean): void;
|
|
221
222
|
/** Draw a debug poly in world space
|
|
222
223
|
* @param {Vector2} pos
|
|
223
224
|
* @param {Array<Vector2>} points
|
|
@@ -225,39 +226,45 @@ declare module "littlejsengine" {
|
|
|
225
226
|
* @param {number} [time]
|
|
226
227
|
* @param {number} [angle]
|
|
227
228
|
* @param {boolean} [fill]
|
|
229
|
+
* @param {boolean} [screenSpace]
|
|
228
230
|
* @memberof Debug */
|
|
229
|
-
export function debugPoly(pos: Vector2, points: Array<Vector2>, color?: Color | string, time?: number, angle?: number, fill?: boolean): void;
|
|
231
|
+
export function debugPoly(pos: Vector2, points: Array<Vector2>, color?: Color | string, time?: number, angle?: number, fill?: boolean, screenSpace?: boolean): void;
|
|
230
232
|
/** Draw a debug circle in world space
|
|
231
233
|
* @param {Vector2} pos
|
|
232
234
|
* @param {number} [size] - diameter
|
|
233
235
|
* @param {Color|string} [color]
|
|
234
236
|
* @param {number} [time]
|
|
235
237
|
* @param {boolean} [fill]
|
|
238
|
+
* @param {boolean} [screenSpace]
|
|
236
239
|
* @memberof Debug */
|
|
237
|
-
export function debugCircle(pos: Vector2, size?: number, color?: Color | string, time?: number, fill?: boolean): void;
|
|
240
|
+
export function debugCircle(pos: Vector2, size?: number, color?: Color | string, time?: number, fill?: boolean, screenSpace?: boolean): void;
|
|
238
241
|
/** Draw a debug point in world space
|
|
239
242
|
* @param {Vector2} pos
|
|
240
243
|
* @param {Color|string} [color]
|
|
241
244
|
* @param {number} [time]
|
|
242
245
|
* @param {number} [angle]
|
|
246
|
+
* @param {boolean} [screenSpace]
|
|
243
247
|
* @memberof Debug */
|
|
244
|
-
export function debugPoint(pos: Vector2, color?: Color | string, time?: number, angle?: number): void;
|
|
248
|
+
export function debugPoint(pos: Vector2, color?: Color | string, time?: number, angle?: number, screenSpace?: boolean): void;
|
|
245
249
|
/** Draw a debug line in world space
|
|
246
250
|
* @param {Vector2} posA
|
|
247
251
|
* @param {Vector2} posB
|
|
248
252
|
* @param {Color|string} [color]
|
|
249
253
|
* @param {number} [width]
|
|
250
254
|
* @param {number} [time]
|
|
255
|
+
* @param {boolean} [screenSpace]
|
|
251
256
|
* @memberof Debug */
|
|
252
|
-
export function debugLine(posA: Vector2, posB: Vector2, color?: Color | string, width?: number, time?: number): void;
|
|
257
|
+
export function debugLine(posA: Vector2, posB: Vector2, color?: Color | string, width?: number, time?: number, screenSpace?: boolean): void;
|
|
253
258
|
/** Draw a debug combined axis aligned bounding box in world space
|
|
254
259
|
* @param {Vector2} posA
|
|
255
260
|
* @param {Vector2} sizeA
|
|
256
261
|
* @param {Vector2} posB
|
|
257
262
|
* @param {Vector2} sizeB
|
|
258
263
|
* @param {Color|string} [color]
|
|
264
|
+
* @param {number} [time]
|
|
265
|
+
* @param {boolean} [screenSpace]
|
|
259
266
|
* @memberof Debug */
|
|
260
|
-
export function debugOverlap(posA: Vector2, sizeA: Vector2, posB: Vector2, sizeB: Vector2, color?: Color | string): void;
|
|
267
|
+
export function debugOverlap(posA: Vector2, sizeA: Vector2, posB: Vector2, sizeB: Vector2, color?: Color | string, time?: number, screenSpace?: boolean): void;
|
|
261
268
|
/** Draw a debug axis aligned bounding box in world space
|
|
262
269
|
* @param {string} text
|
|
263
270
|
* @param {Vector2} pos
|
|
@@ -266,8 +273,9 @@ declare module "littlejsengine" {
|
|
|
266
273
|
* @param {number} [time]
|
|
267
274
|
* @param {number} [angle]
|
|
268
275
|
* @param {string} [font]
|
|
276
|
+
* @param {boolean} [screenSpace]
|
|
269
277
|
* @memberof Debug */
|
|
270
|
-
export function debugText(text: string, pos: Vector2, size?: number, color?: Color | string, time?: number, angle?: number, font?: string): void;
|
|
278
|
+
export function debugText(text: string, pos: Vector2, size?: number, color?: Color | string, time?: number, angle?: number, font?: string, screenSpace?: boolean): void;
|
|
271
279
|
/** Clear all debug primitives in the list
|
|
272
280
|
* @memberof Debug */
|
|
273
281
|
export function debugClear(): void;
|
|
@@ -3146,6 +3154,12 @@ declare module "littlejsengine" {
|
|
|
3146
3154
|
defaultSoundRelease: any;
|
|
3147
3155
|
/** @property {Sound} - Default sound when interactive UI element is clicked */
|
|
3148
3156
|
defaultSoundClick: any;
|
|
3157
|
+
/** @property {Color} - Color for shadow */
|
|
3158
|
+
defaultShadowColor: Color;
|
|
3159
|
+
/** @property {number} - Size of shadow blur */
|
|
3160
|
+
defaultShadowBlur: number;
|
|
3161
|
+
/** @property {Vector2} - Offset of shadow blur */
|
|
3162
|
+
defaultShadowOffset: Vector2;
|
|
3149
3163
|
/** @property {Array<UIObject>} - List of all UI elements */
|
|
3150
3164
|
uiObjects: any[];
|
|
3151
3165
|
/** @property {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} - Context to render UI elements to */
|
|
@@ -3165,8 +3179,11 @@ declare module "littlejsengine" {
|
|
|
3165
3179
|
* @param {number} [lineWidth]
|
|
3166
3180
|
* @param {Color} [lineColor]
|
|
3167
3181
|
* @param {number} [cornerRadius]
|
|
3168
|
-
* @param {Color} [gradientColor]
|
|
3169
|
-
|
|
3182
|
+
* @param {Color} [gradientColor]
|
|
3183
|
+
* @param {Color} [shadowColor]
|
|
3184
|
+
* @param {number} [shadowBlur]
|
|
3185
|
+
* @param {Color} [shadowOffset] */
|
|
3186
|
+
drawRect(pos: Vector2, size: Vector2, color?: Color, lineWidth?: number, lineColor?: Color, cornerRadius?: number, gradientColor?: Color, shadowColor?: Color, shadowBlur?: number, shadowOffset?: Color): void;
|
|
3170
3187
|
/** Draw a line to the UI context
|
|
3171
3188
|
* @param {Vector2} posA
|
|
3172
3189
|
* @param {Vector2} posB
|
|
@@ -3283,6 +3300,12 @@ declare module "littlejsengine" {
|
|
|
3283
3300
|
dragActivate: boolean;
|
|
3284
3301
|
/** @property {boolean} - True if this can be a hover object */
|
|
3285
3302
|
canBeHover: boolean;
|
|
3303
|
+
/** @property {Color} - Color for shadow, undefined if no shadow */
|
|
3304
|
+
shadowColor: Color;
|
|
3305
|
+
/** @property {number} - Size of shadow blur */
|
|
3306
|
+
shadowBlur: number;
|
|
3307
|
+
/** @property {Vector2} - Offset of shadow blur */
|
|
3308
|
+
shadowOffset: Vector2;
|
|
3286
3309
|
/** @property {Vector2} - How much to offset the text shadow or undefined */
|
|
3287
3310
|
textShadow: any;
|
|
3288
3311
|
/** Add a child UIObject to this object
|
package/dist/littlejs.esm.js
CHANGED
|
@@ -33,7 +33,7 @@ const engineName = 'LittleJS';
|
|
|
33
33
|
* @type {string}
|
|
34
34
|
* @default
|
|
35
35
|
* @memberof Engine */
|
|
36
|
-
const engineVersion = '1.15.
|
|
36
|
+
const engineVersion = '1.15.3';
|
|
37
37
|
|
|
38
38
|
/** Frames per second to update
|
|
39
39
|
* @type {number}
|
|
@@ -790,8 +790,9 @@ function LOG(...output) { console.log(...output); }
|
|
|
790
790
|
* @param {number} [time]
|
|
791
791
|
* @param {number} [angle]
|
|
792
792
|
* @param {boolean} [fill]
|
|
793
|
+
* @param {boolean} [screenSpace]
|
|
793
794
|
* @memberof Debug */
|
|
794
|
-
function debugRect(pos, size=vec2(), color=WHITE, time=0, angle=0, fill=false)
|
|
795
|
+
function debugRect(pos, size=vec2(), color=WHITE, time=0, angle=0, fill=false, screenSpace=false)
|
|
795
796
|
{
|
|
796
797
|
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
797
798
|
ASSERT(isVector2(size), 'size must be a vec2');
|
|
@@ -806,7 +807,7 @@ function debugRect(pos, size=vec2(), color=WHITE, time=0, angle=0, fill=false)
|
|
|
806
807
|
pos = pos.copy();
|
|
807
808
|
size = size.copy();
|
|
808
809
|
const timer = new Timer(time);
|
|
809
|
-
debugPrimitives.push({pos:pos.copy(), size:size.copy(), color, timer, angle, fill});
|
|
810
|
+
debugPrimitives.push({pos:pos.copy(), size:size.copy(), color, timer, angle, fill, screenSpace});
|
|
810
811
|
}
|
|
811
812
|
|
|
812
813
|
/** Draw a debug poly in world space
|
|
@@ -816,8 +817,9 @@ function debugRect(pos, size=vec2(), color=WHITE, time=0, angle=0, fill=false)
|
|
|
816
817
|
* @param {number} [time]
|
|
817
818
|
* @param {number} [angle]
|
|
818
819
|
* @param {boolean} [fill]
|
|
820
|
+
* @param {boolean} [screenSpace]
|
|
819
821
|
* @memberof Debug */
|
|
820
|
-
function debugPoly(pos, points, color=WHITE, time=0, angle=0, fill=false)
|
|
822
|
+
function debugPoly(pos, points, color=WHITE, time=0, angle=0, fill=false, screenSpace=false)
|
|
821
823
|
{
|
|
822
824
|
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
823
825
|
ASSERT(isArray(points), 'points must be an array');
|
|
@@ -830,7 +832,7 @@ function debugPoly(pos, points, color=WHITE, time=0, angle=0, fill=false)
|
|
|
830
832
|
pos = pos.copy();
|
|
831
833
|
points = points.map(p=>p.copy());
|
|
832
834
|
const timer = new Timer(time);
|
|
833
|
-
debugPrimitives.push({pos, points, color, timer, angle, fill});
|
|
835
|
+
debugPrimitives.push({pos, points, color, timer, angle, fill, screenSpace});
|
|
834
836
|
}
|
|
835
837
|
|
|
836
838
|
/** Draw a debug circle in world space
|
|
@@ -839,8 +841,9 @@ function debugPoly(pos, points, color=WHITE, time=0, angle=0, fill=false)
|
|
|
839
841
|
* @param {Color|string} [color]
|
|
840
842
|
* @param {number} [time]
|
|
841
843
|
* @param {boolean} [fill]
|
|
844
|
+
* @param {boolean} [screenSpace]
|
|
842
845
|
* @memberof Debug */
|
|
843
|
-
function debugCircle(pos, size=0, color=WHITE, time=0, fill=false)
|
|
846
|
+
function debugCircle(pos, size=0, color=WHITE, time=0, fill=false, screenSpace=false)
|
|
844
847
|
{
|
|
845
848
|
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
846
849
|
ASSERT(isNumber(size), 'size must be a number');
|
|
@@ -851,7 +854,7 @@ function debugCircle(pos, size=0, color=WHITE, time=0, fill=false)
|
|
|
851
854
|
color = color.toString();
|
|
852
855
|
pos = pos.copy();
|
|
853
856
|
const timer = new Timer(time);
|
|
854
|
-
debugPrimitives.push({pos, size, color, timer, angle:0, fill});
|
|
857
|
+
debugPrimitives.push({pos, size, color, timer, angle:0, fill, screenSpace});
|
|
855
858
|
}
|
|
856
859
|
|
|
857
860
|
/** Draw a debug point in world space
|
|
@@ -859,9 +862,10 @@ function debugCircle(pos, size=0, color=WHITE, time=0, fill=false)
|
|
|
859
862
|
* @param {Color|string} [color]
|
|
860
863
|
* @param {number} [time]
|
|
861
864
|
* @param {number} [angle]
|
|
865
|
+
* @param {boolean} [screenSpace]
|
|
862
866
|
* @memberof Debug */
|
|
863
|
-
function debugPoint(pos, color, time, angle)
|
|
864
|
-
{ debugRect(pos, undefined, color, time, angle); }
|
|
867
|
+
function debugPoint(pos, color, time, angle, screenSpace=false)
|
|
868
|
+
{ debugRect(pos, undefined, color, time, angle, false, screenSpace); }
|
|
865
869
|
|
|
866
870
|
/** Draw a debug line in world space
|
|
867
871
|
* @param {Vector2} posA
|
|
@@ -869,8 +873,9 @@ function debugPoint(pos, color, time, angle)
|
|
|
869
873
|
* @param {Color|string} [color]
|
|
870
874
|
* @param {number} [width]
|
|
871
875
|
* @param {number} [time]
|
|
876
|
+
* @param {boolean} [screenSpace]
|
|
872
877
|
* @memberof Debug */
|
|
873
|
-
function debugLine(posA, posB, color, width=.1, time)
|
|
878
|
+
function debugLine(posA, posB, color, width=.1, time, screenSpace=false)
|
|
874
879
|
{
|
|
875
880
|
ASSERT(isVector2(posA), 'posA must be a vec2');
|
|
876
881
|
ASSERT(isVector2(posB), 'posB must be sa vec2');
|
|
@@ -878,7 +883,7 @@ function debugLine(posA, posB, color, width=.1, time)
|
|
|
878
883
|
|
|
879
884
|
const halfDelta = vec2((posB.x - posA.x)/2, (posB.y - posA.y)/2);
|
|
880
885
|
const size = vec2(width, halfDelta.length()*2);
|
|
881
|
-
debugRect(posA.add(halfDelta), size, color, time, halfDelta.angle(), true);
|
|
886
|
+
debugRect(posA.add(halfDelta), size, color, time, halfDelta.angle(), true, screenSpace);
|
|
882
887
|
}
|
|
883
888
|
|
|
884
889
|
/** Draw a debug combined axis aligned bounding box in world space
|
|
@@ -887,8 +892,10 @@ function debugLine(posA, posB, color, width=.1, time)
|
|
|
887
892
|
* @param {Vector2} posB
|
|
888
893
|
* @param {Vector2} sizeB
|
|
889
894
|
* @param {Color|string} [color]
|
|
895
|
+
* @param {number} [time]
|
|
896
|
+
* @param {boolean} [screenSpace]
|
|
890
897
|
* @memberof Debug */
|
|
891
|
-
function debugOverlap(posA, sizeA, posB, sizeB, color)
|
|
898
|
+
function debugOverlap(posA, sizeA, posB, sizeB, color, time, screenSpace=false)
|
|
892
899
|
{
|
|
893
900
|
ASSERT(isVector2(posA), 'posA must be a vec2');
|
|
894
901
|
ASSERT(isVector2(posB), 'posB must be a vec2');
|
|
@@ -903,7 +910,7 @@ function debugOverlap(posA, sizeA, posB, sizeB, color)
|
|
|
903
910
|
max(posA.x + sizeA.x/2, posB.x + sizeB.x/2),
|
|
904
911
|
max(posA.y + sizeA.y/2, posB.y + sizeB.y/2)
|
|
905
912
|
);
|
|
906
|
-
debugRect(minPos.lerp(maxPos,.5), maxPos.subtract(minPos), color);
|
|
913
|
+
debugRect(minPos.lerp(maxPos,.5), maxPos.subtract(minPos), color, time, 0, false, screenSpace);
|
|
907
914
|
}
|
|
908
915
|
|
|
909
916
|
/** Draw a debug axis aligned bounding box in world space
|
|
@@ -914,8 +921,9 @@ function debugOverlap(posA, sizeA, posB, sizeB, color)
|
|
|
914
921
|
* @param {number} [time]
|
|
915
922
|
* @param {number} [angle]
|
|
916
923
|
* @param {string} [font]
|
|
924
|
+
* @param {boolean} [screenSpace]
|
|
917
925
|
* @memberof Debug */
|
|
918
|
-
function debugText(text, pos, size=1, color=WHITE, time=0, angle=0, font='monospace')
|
|
926
|
+
function debugText(text, pos, size=1, color=WHITE, time=0, angle=0, font='monospace', screenSpace=false)
|
|
919
927
|
{
|
|
920
928
|
ASSERT(isString(text), 'text must be a string');
|
|
921
929
|
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
@@ -929,7 +937,7 @@ function debugText(text, pos, size=1, color=WHITE, time=0, angle=0, font='monosp
|
|
|
929
937
|
color = color.toString();
|
|
930
938
|
pos = pos.copy();
|
|
931
939
|
const timer = new Timer(time);
|
|
932
|
-
debugPrimitives.push({text, pos, size, color, timer, angle, font});
|
|
940
|
+
debugPrimitives.push({text, pos, size, color, timer, angle, font, screenSpace});
|
|
933
941
|
}
|
|
934
942
|
|
|
935
943
|
/** Clear all debug primitives in the list
|
|
@@ -1139,21 +1147,26 @@ function debugRender()
|
|
|
1139
1147
|
{
|
|
1140
1148
|
// draw debug primitives
|
|
1141
1149
|
overlayContext.lineWidth = 2;
|
|
1142
|
-
const pointSize = debugPointSize * cameraScale;
|
|
1143
1150
|
debugPrimitives.forEach(p=>
|
|
1144
1151
|
{
|
|
1145
1152
|
overlayContext.save();
|
|
1146
1153
|
|
|
1147
1154
|
// create canvas transform from world space to screen space
|
|
1148
|
-
|
|
1155
|
+
// without scaling because we want consistent pixel sizes
|
|
1156
|
+
let pos = p.pos, scale = 1, angle = p.angle;
|
|
1157
|
+
if (!p.screenSpace)
|
|
1158
|
+
{
|
|
1159
|
+
pos = worldToScreen(p.pos);
|
|
1160
|
+
scale = cameraScale;
|
|
1161
|
+
angle -= cameraAngle;
|
|
1162
|
+
}
|
|
1149
1163
|
overlayContext.translate(pos.x|0, pos.y|0);
|
|
1150
|
-
overlayContext.rotate(
|
|
1164
|
+
overlayContext.rotate(angle);
|
|
1151
1165
|
overlayContext.scale(1, p.text ? 1 : -1);
|
|
1152
1166
|
overlayContext.fillStyle = overlayContext.strokeStyle = p.color;
|
|
1153
|
-
|
|
1154
1167
|
if (p.text !== undefined)
|
|
1155
1168
|
{
|
|
1156
|
-
overlayContext.font = p.size*
|
|
1169
|
+
overlayContext.font = p.size*scale + 'px '+ p.font;
|
|
1157
1170
|
overlayContext.textAlign = 'center';
|
|
1158
1171
|
overlayContext.textBaseline = 'middle';
|
|
1159
1172
|
overlayContext.fillText(p.text, 0, 0);
|
|
@@ -1164,7 +1177,7 @@ function debugRender()
|
|
|
1164
1177
|
overlayContext.beginPath();
|
|
1165
1178
|
for (const point of p.points)
|
|
1166
1179
|
{
|
|
1167
|
-
const p2 = point.scale(
|
|
1180
|
+
const p2 = point.scale(scale).floor();
|
|
1168
1181
|
overlayContext.lineTo(p2.x, p2.y);
|
|
1169
1182
|
}
|
|
1170
1183
|
overlayContext.closePath();
|
|
@@ -1174,13 +1187,14 @@ function debugRender()
|
|
|
1174
1187
|
else if (p.size === 0 || (p.size.x === 0 && p.size.y === 0))
|
|
1175
1188
|
{
|
|
1176
1189
|
// point
|
|
1190
|
+
const pointSize = debugPointSize * scale;
|
|
1177
1191
|
overlayContext.fillRect(-pointSize/2, -1, pointSize, 3);
|
|
1178
1192
|
overlayContext.fillRect(-1, -pointSize/2, 3, pointSize);
|
|
1179
1193
|
}
|
|
1180
1194
|
else if (p.size.x !== undefined)
|
|
1181
1195
|
{
|
|
1182
1196
|
// rect
|
|
1183
|
-
const s = p.size.scale(
|
|
1197
|
+
const s = p.size.scale(scale).floor();
|
|
1184
1198
|
const w = s.x, h = s.y;
|
|
1185
1199
|
p.fill && overlayContext.fillRect(-w/2|0, -h/2|0, w, h);
|
|
1186
1200
|
overlayContext.strokeRect(-w/2|0, -h/2|0, w, h);
|
|
@@ -1189,7 +1203,7 @@ function debugRender()
|
|
|
1189
1203
|
{
|
|
1190
1204
|
// circle
|
|
1191
1205
|
overlayContext.beginPath();
|
|
1192
|
-
overlayContext.arc(0, 0, p.size*
|
|
1206
|
+
overlayContext.arc(0, 0, p.size*scale/2, 0, 9);
|
|
1193
1207
|
p.fill && overlayContext.fill();
|
|
1194
1208
|
overlayContext.stroke();
|
|
1195
1209
|
}
|
|
@@ -3644,7 +3658,9 @@ class EngineObject
|
|
|
3644
3658
|
{
|
|
3645
3659
|
ASSERT(child.parent === this && this.children.includes(child));
|
|
3646
3660
|
ASSERT(child instanceof EngineObject, 'child must be an EngineObject');
|
|
3647
|
-
this.children.
|
|
3661
|
+
const index = this.children.indexOf(child);
|
|
3662
|
+
ASSERT(index >= 0, 'child not found in children array');
|
|
3663
|
+
index >= 0 && this.children.splice(index, 1);
|
|
3648
3664
|
child.parent = 0;
|
|
3649
3665
|
}
|
|
3650
3666
|
|
|
@@ -3963,15 +3979,11 @@ function drawTile(pos, size=new Vector2(1), tileInfo, color=WHITE,
|
|
|
3963
3979
|
|
|
3964
3980
|
const textureInfo = tileInfo && tileInfo.textureInfo;
|
|
3965
3981
|
const bleedScale = tileInfo ? tileInfo.bleedScale : 0;
|
|
3966
|
-
if (useWebGL)
|
|
3982
|
+
if (useWebGL && glEnable)
|
|
3967
3983
|
{
|
|
3968
3984
|
ASSERT(!!glContext, 'WebGL is not enabled!');
|
|
3969
3985
|
if (screenSpace)
|
|
3970
|
-
|
|
3971
|
-
// convert to world space
|
|
3972
|
-
pos = screenToWorld(pos);
|
|
3973
|
-
size = size.scale(1/cameraScale);
|
|
3974
|
-
}
|
|
3986
|
+
[pos, size, angle] = screenToWorldTransform(pos, size, angle);
|
|
3975
3987
|
if (textureInfo)
|
|
3976
3988
|
{
|
|
3977
3989
|
// calculate uvs and render
|
|
@@ -4059,7 +4071,8 @@ function drawRectGradient(pos, size, colorTop=WHITE, colorBottom=BLACK, angle=0,
|
|
|
4059
4071
|
ASSERT(isColor(colorTop) && isColor(colorBottom), 'color is invalid');
|
|
4060
4072
|
ASSERT(isNumber(angle), 'angle must be a number');
|
|
4061
4073
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
4062
|
-
|
|
4074
|
+
|
|
4075
|
+
if (useWebGL && glEnable)
|
|
4063
4076
|
{
|
|
4064
4077
|
ASSERT(!!glContext, 'WebGL is not enabled!');
|
|
4065
4078
|
if (screenSpace)
|
|
@@ -4067,6 +4080,7 @@ function drawRectGradient(pos, size, colorTop=WHITE, colorBottom=BLACK, angle=0,
|
|
|
4067
4080
|
// convert to world space
|
|
4068
4081
|
pos = screenToWorld(pos);
|
|
4069
4082
|
size = size.scale(1/cameraScale);
|
|
4083
|
+
angle += cameraAngle;
|
|
4070
4084
|
}
|
|
4071
4085
|
// build 4 corner points for the rectangle
|
|
4072
4086
|
const points = [], colors = [];
|
|
@@ -4122,17 +4136,14 @@ function drawLineList(points, width=.1, color, wrap=false, pos=vec2(), angle=0,
|
|
|
4122
4136
|
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
4123
4137
|
ASSERT(isNumber(angle), 'angle must be a number');
|
|
4124
4138
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
4125
|
-
|
|
4139
|
+
|
|
4140
|
+
if (useWebGL && glEnable)
|
|
4126
4141
|
{
|
|
4127
4142
|
ASSERT(!!glContext, 'WebGL is not enabled!');
|
|
4128
|
-
let
|
|
4143
|
+
let size = vec2(1);
|
|
4129
4144
|
if (screenSpace)
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
pos = screenToWorld(pos);
|
|
4133
|
-
scale = 1/cameraScale;
|
|
4134
|
-
}
|
|
4135
|
-
glDrawOutlineTransform(points, color.rgbaInt(), width, pos.x, pos.y, scale, scale, angle, wrap);
|
|
4145
|
+
[pos, size, angle] = screenToWorldTransform(pos, size, angle);
|
|
4146
|
+
glDrawOutlineTransform(points, color.rgbaInt(), width, pos.x, pos.y, size.x, size.y, angle, wrap);
|
|
4136
4147
|
}
|
|
4137
4148
|
else
|
|
4138
4149
|
{
|
|
@@ -4228,19 +4239,15 @@ function drawPoly(points, color=WHITE, lineWidth=0, lineColor=BLACK, pos=vec2(),
|
|
|
4228
4239
|
ASSERT(isNumber(angle), 'angle must be a number');
|
|
4229
4240
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
4230
4241
|
|
|
4231
|
-
if (useWebGL)
|
|
4242
|
+
if (useWebGL && glEnable)
|
|
4232
4243
|
{
|
|
4233
4244
|
ASSERT(!!glContext, 'WebGL is not enabled!');
|
|
4234
|
-
let
|
|
4245
|
+
let size = vec2(1);
|
|
4235
4246
|
if (screenSpace)
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
pos = screenToWorld(pos);
|
|
4239
|
-
scale = 1/cameraScale;
|
|
4240
|
-
}
|
|
4241
|
-
glDrawPointsTransform(points, color.rgbaInt(), pos.x, pos.y, scale, scale, angle);
|
|
4247
|
+
[pos, size, angle] = screenToWorldTransform(pos, size, angle);
|
|
4248
|
+
glDrawPointsTransform(points, color.rgbaInt(), pos.x, pos.y, size.x, size.y, angle);
|
|
4242
4249
|
if (lineWidth > 0)
|
|
4243
|
-
glDrawOutlineTransform(points, lineColor.rgbaInt(), lineWidth, pos.x, pos.y,
|
|
4250
|
+
glDrawOutlineTransform(points, lineColor.rgbaInt(), lineWidth, pos.x, pos.y, size.x, size.y, angle);
|
|
4244
4251
|
}
|
|
4245
4252
|
else
|
|
4246
4253
|
{
|
|
@@ -4283,7 +4290,7 @@ function drawEllipse(pos, size=vec2(1), color=WHITE, angle=0, lineWidth=0, lineC
|
|
|
4283
4290
|
ASSERT(lineWidth >= 0 && lineWidth < size.x && lineWidth < size.y, 'invalid lineWidth');
|
|
4284
4291
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
4285
4292
|
|
|
4286
|
-
if (useWebGL)
|
|
4293
|
+
if (useWebGL && glEnable)
|
|
4287
4294
|
{
|
|
4288
4295
|
// draw as a regular polygon
|
|
4289
4296
|
const sides = glCircleSides;
|
|
@@ -4346,14 +4353,10 @@ function drawCanvas2D(pos, size, angle=0, mirror=false, drawFunction, screenSpac
|
|
|
4346
4353
|
ASSERT(typeof drawFunction === 'function', 'drawFunction must be a function');
|
|
4347
4354
|
|
|
4348
4355
|
if (!screenSpace)
|
|
4349
|
-
|
|
4350
|
-
// transform from world space to screen space
|
|
4351
|
-
pos = worldToScreen(pos);
|
|
4352
|
-
size = size.scale(cameraScale);
|
|
4353
|
-
}
|
|
4356
|
+
[pos, size, angle] = worldToScreenTransform(pos, size, angle);
|
|
4354
4357
|
context.save();
|
|
4355
4358
|
context.translate(pos.x+.5, pos.y+.5);
|
|
4356
|
-
context.rotate(angle
|
|
4359
|
+
context.rotate(angle);
|
|
4357
4360
|
context.scale(mirror ? -size.x : size.x, -size.y);
|
|
4358
4361
|
drawFunction(context);
|
|
4359
4362
|
context.restore();
|
|
@@ -4379,7 +4382,14 @@ function drawCanvas2D(pos, size, angle=0, mirror=false, drawFunction, screenSpac
|
|
|
4379
4382
|
* @memberof Draw */
|
|
4380
4383
|
function drawText(text, pos, size=1, color, lineWidth=0, lineColor, textAlign, font, fontStyle, maxWidth, angle=0, context=drawContext)
|
|
4381
4384
|
{
|
|
4382
|
-
|
|
4385
|
+
// convert to screen space
|
|
4386
|
+
pos = worldToScreen(pos);
|
|
4387
|
+
size *= cameraScale;
|
|
4388
|
+
lineWidth *= cameraScale;
|
|
4389
|
+
angle -= cameraAngle;
|
|
4390
|
+
angle *= -1;
|
|
4391
|
+
|
|
4392
|
+
drawTextScreen(text, pos, size, color, lineWidth, lineColor, textAlign, font, fontStyle, maxWidth, angle, context);
|
|
4383
4393
|
}
|
|
4384
4394
|
|
|
4385
4395
|
/** Draw text on overlay canvas in world space
|
|
@@ -4538,6 +4548,36 @@ function worldToScreenDelta(worldDelta)
|
|
|
4538
4548
|
return new Vector2(x * cameraScale, y * -cameraScale);
|
|
4539
4549
|
}
|
|
4540
4550
|
|
|
4551
|
+
/** Convert screen space transform to world space
|
|
4552
|
+
* @param {Vector2} screenPos
|
|
4553
|
+
* @param {Vector2} screenSize
|
|
4554
|
+
* @param {number} [screenAngle]
|
|
4555
|
+
* @return {[Vector2, Vector2, number]} - [pos, size, angle]
|
|
4556
|
+
* @memberof Draw */
|
|
4557
|
+
function screenToWorldTransform(screenPos, screenSize, screenAngle=0)
|
|
4558
|
+
{
|
|
4559
|
+
return [
|
|
4560
|
+
screenToWorld(screenPos),
|
|
4561
|
+
screenSize.scale(1/cameraScale),
|
|
4562
|
+
screenAngle + cameraAngle
|
|
4563
|
+
];
|
|
4564
|
+
}
|
|
4565
|
+
|
|
4566
|
+
/** Convert world space transform to screen space
|
|
4567
|
+
* @param {Vector2} worldPos
|
|
4568
|
+
* @param {Vector2} worldSize
|
|
4569
|
+
* @param {number} [worldAngle]
|
|
4570
|
+
* @return {[Vector2, Vector2, number]} - [pos, size, angle]
|
|
4571
|
+
* @memberof Draw */
|
|
4572
|
+
function worldToScreenTransform(worldPos, worldSize, worldAngle=0)
|
|
4573
|
+
{
|
|
4574
|
+
return [
|
|
4575
|
+
worldToScreen(worldPos),
|
|
4576
|
+
worldSize.scale(cameraScale),
|
|
4577
|
+
worldAngle - cameraAngle
|
|
4578
|
+
];
|
|
4579
|
+
}
|
|
4580
|
+
|
|
4541
4581
|
/** Get the camera's visible area in world space
|
|
4542
4582
|
* @return {Vector2}
|
|
4543
4583
|
* @memberof Draw */
|
|
@@ -4945,7 +4985,7 @@ function inputUpdate()
|
|
|
4945
4985
|
if (headlessMode) return;
|
|
4946
4986
|
|
|
4947
4987
|
// clear input when lost focus (prevent stuck keys)
|
|
4948
|
-
if(!(touchInputEnable && isTouchDevice) && !document.hasFocus())
|
|
4988
|
+
if (!(touchInputEnable && isTouchDevice) && !document.hasFocus())
|
|
4949
4989
|
inputClear();
|
|
4950
4990
|
|
|
4951
4991
|
// update mouse world space position and delta
|
|
@@ -5503,7 +5543,6 @@ class Sound
|
|
|
5503
5543
|
ASSERT(isNumber(pitch), 'pitch must be a number');
|
|
5504
5544
|
ASSERT(isNumber(randomnessScale), 'randomnessScale must be a number');
|
|
5505
5545
|
|
|
5506
|
-
|
|
5507
5546
|
if (!soundEnable || headlessMode) return;
|
|
5508
5547
|
if (!this.sampleChannels) return;
|
|
5509
5548
|
|
|
@@ -6636,7 +6675,7 @@ class TileCollisionLayer extends TileLayer
|
|
|
6636
6675
|
// remove from collision layers array and destroy
|
|
6637
6676
|
const index = tileCollisionLayers.indexOf(this);
|
|
6638
6677
|
ASSERT(index >= 0, 'tile collision layer not found in array');
|
|
6639
|
-
tileCollisionLayers.splice(index, 1);
|
|
6678
|
+
index >= 0 && tileCollisionLayers.splice(index, 1);
|
|
6640
6679
|
super.destroy();
|
|
6641
6680
|
}
|
|
6642
6681
|
|
|
@@ -8682,6 +8721,7 @@ class UISystemPlugin
|
|
|
8682
8721
|
ASSERT(!uiSystem, 'UI system already initialized');
|
|
8683
8722
|
uiSystem = this;
|
|
8684
8723
|
|
|
8724
|
+
// default settings
|
|
8685
8725
|
/** @property {Color} - Default fill color for UI elements */
|
|
8686
8726
|
this.defaultColor = WHITE;
|
|
8687
8727
|
/** @property {Color} - Default outline color for UI elements */
|
|
@@ -8710,6 +8750,13 @@ class UISystemPlugin
|
|
|
8710
8750
|
this.defaultSoundRelease = undefined;
|
|
8711
8751
|
/** @property {Sound} - Default sound when interactive UI element is clicked */
|
|
8712
8752
|
this.defaultSoundClick = undefined;
|
|
8753
|
+
/** @property {Color} - Color for shadow */
|
|
8754
|
+
this.defaultShadowColor = CLEAR_BLACK;
|
|
8755
|
+
/** @property {number} - Size of shadow blur */
|
|
8756
|
+
this.defaultShadowBlur = 5;
|
|
8757
|
+
/** @property {Vector2} - Offset of shadow blur */
|
|
8758
|
+
this.defaultShadowOffset = vec2(5);
|
|
8759
|
+
// system state
|
|
8713
8760
|
/** @property {Array<UIObject>} - List of all UI elements */
|
|
8714
8761
|
this.uiObjects = [];
|
|
8715
8762
|
/** @property {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} - Context to render UI elements to */
|
|
@@ -8800,8 +8847,11 @@ class UISystemPlugin
|
|
|
8800
8847
|
* @param {number} [lineWidth]
|
|
8801
8848
|
* @param {Color} [lineColor]
|
|
8802
8849
|
* @param {number} [cornerRadius]
|
|
8803
|
-
* @param {Color} [gradientColor]
|
|
8804
|
-
|
|
8850
|
+
* @param {Color} [gradientColor]
|
|
8851
|
+
* @param {Color} [shadowColor]
|
|
8852
|
+
* @param {number} [shadowBlur]
|
|
8853
|
+
* @param {Color} [shadowOffset] */
|
|
8854
|
+
drawRect(pos, size, color=WHITE, lineWidth=0, lineColor=BLACK, cornerRadius=0, gradientColor, shadowColor=BLACK, shadowBlur=0, shadowOffset=vec2())
|
|
8805
8855
|
{
|
|
8806
8856
|
ASSERT(isVector2(pos), 'pos must be a vec2');
|
|
8807
8857
|
ASSERT(isVector2(size), 'size must be a vec2');
|
|
@@ -8823,12 +8873,22 @@ class UISystemPlugin
|
|
|
8823
8873
|
}
|
|
8824
8874
|
else
|
|
8825
8875
|
context.fillStyle = color.toString();
|
|
8876
|
+
if (shadowBlur || shadowOffset.x || shadowOffset.y)
|
|
8877
|
+
if (shadowColor.a > 0)
|
|
8878
|
+
{
|
|
8879
|
+
// setup shadow
|
|
8880
|
+
context.shadowColor = shadowColor.toString();
|
|
8881
|
+
context.shadowBlur = shadowBlur;
|
|
8882
|
+
context.shadowOffsetX = shadowOffset.x;
|
|
8883
|
+
context.shadowOffsetY = shadowOffset.y;
|
|
8884
|
+
}
|
|
8826
8885
|
context.beginPath();
|
|
8827
8886
|
if (cornerRadius && context['roundRect'])
|
|
8828
8887
|
context['roundRect'](pos.x-size.x/2, pos.y-size.y/2, size.x, size.y, cornerRadius);
|
|
8829
8888
|
else
|
|
8830
8889
|
context.rect(pos.x-size.x/2, pos.y-size.y/2, size.x, size.y);
|
|
8831
8890
|
context.fill();
|
|
8891
|
+
context.shadowColor = '#0000'
|
|
8832
8892
|
if (lineWidth)
|
|
8833
8893
|
{
|
|
8834
8894
|
context.strokeStyle = lineColor.toString();
|
|
@@ -9017,6 +9077,12 @@ class UIObject
|
|
|
9017
9077
|
this.dragActivate = false;
|
|
9018
9078
|
/** @property {boolean} - True if this can be a hover object */
|
|
9019
9079
|
this.canBeHover = true;
|
|
9080
|
+
/** @property {Color} - Color for shadow, undefined if no shadow */
|
|
9081
|
+
this.shadowColor = uiSystem.defaultShadowColor?.copy();
|
|
9082
|
+
/** @property {number} - Size of shadow blur */
|
|
9083
|
+
this.shadowBlur = uiSystem.defaultShadowBlur;
|
|
9084
|
+
/** @property {Vector2} - Offset of shadow blur */
|
|
9085
|
+
this.shadowOffset = uiSystem.defaultShadowOffset.copy();
|
|
9020
9086
|
uiSystem.uiObjects.push(this);
|
|
9021
9087
|
|
|
9022
9088
|
/** @property {Vector2} - How much to offset the text shadow or undefined */
|
|
@@ -9134,7 +9200,7 @@ class UIObject
|
|
|
9134
9200
|
|
|
9135
9201
|
const lineColor = this.interactive && this.isActiveObject() && !this.disabled ? this.color : this.lineColor;
|
|
9136
9202
|
const color = this.disabled ? this.disabledColor : this.interactive ? this.isActiveObject() ? this.activeColor || this.color : this.isHoverObject() ? this.hoverColor : this.color : this.color;
|
|
9137
|
-
uiSystem.drawRect(this.pos, this.size, color, this.lineWidth, lineColor, this.cornerRadius, this.gradientColor);
|
|
9203
|
+
uiSystem.drawRect(this.pos, this.size, color, this.lineWidth, lineColor, this.cornerRadius, this.gradientColor, this.shadowColor, this.shadowBlur, this.shadowOffset);
|
|
9138
9204
|
}
|
|
9139
9205
|
|
|
9140
9206
|
/** Special update when object is not visible */
|