littlejsengine 1.14.5 → 1.14.8
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 +53 -19
- package/dist/littlejs.esm.js +183 -106
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +179 -104
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +178 -103
- package/examples/box2d/game.js +1 -3
- package/examples/box2d/gameObjects.js +2 -2
- package/examples/htmlMenu/game.js +1 -1
- package/examples/index.html +92 -51
- package/examples/puzzle/game.js +1 -2
- package/examples/shorts/animation.js +2 -2
- package/examples/shorts/box2d.js +1 -0
- package/examples/shorts/box2dCar.js +1 -0
- package/examples/shorts/flappyGame.js +2 -1
- package/examples/shorts/helloWorld.js +2 -2
- package/examples/shorts/hillGlideGame.js +6 -3
- package/examples/shorts/maze.js +1 -0
- package/examples/shorts/medals.js +3 -0
- package/examples/shorts/music.js +3 -5
- package/examples/shorts/piano.js +24 -25
- package/examples/shorts/platformer.js +1 -0
- package/examples/shorts/shapes.js +6 -6
- package/examples/shorts/sound.js +21 -32
- package/examples/shorts/spriteAtlas.js +1 -2
- package/examples/shorts/tileLayer.js +1 -0
- package/examples/shorts/tiltedView.js +1 -1
- package/examples/shorts/timers.js +34 -31
- package/examples/shorts/topDown.js +2 -1
- package/examples/shorts/uiSystem.js +15 -10
- package/examples/stress/index.html +1 -1
- package/examples/uiSystem/game.js +1 -1
- package/package.json +1 -1
- package/plugins/uiSystem.js +83 -58
- package/reference.md +1 -0
- package/src/engine.js +23 -6
- package/src/engineDebug.js +1 -1
- package/src/engineDraw.js +19 -12
- package/src/engineExport.js +4 -2
- package/src/engineInput.js +7 -0
- package/src/engineObject.js +4 -4
- package/src/engineSettings.js +11 -1
- package/src/engineTileLayer.js +2 -2
- package/src/engineUtilities.js +9 -2
- package/src/engineWebGL.js +20 -18
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.14.
|
|
36
|
+
const engineVersion = '1.14.8';
|
|
37
37
|
|
|
38
38
|
/** Frames per second to update
|
|
39
39
|
* @type {number}
|
|
@@ -172,15 +172,15 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
|
|
|
172
172
|
frameTimeBufferMS += paused ? 0 : frameTimeDeltaMS;
|
|
173
173
|
if (!debugSpeedUp)
|
|
174
174
|
frameTimeBufferMS = min(frameTimeBufferMS, 50); // clamp min framerate
|
|
175
|
-
if (debugVideoCaptureIsActive())
|
|
176
|
-
frameTimeBufferMS = 0; // no time smoothing when capturing video
|
|
177
|
-
updateCanvas();
|
|
178
175
|
|
|
179
176
|
if (paused)
|
|
180
177
|
{
|
|
178
|
+
updateCanvas();
|
|
179
|
+
|
|
181
180
|
// update object transforms even when paused
|
|
182
181
|
for (const o of engineObjects)
|
|
183
182
|
o.parent || o.updateTransforms();
|
|
183
|
+
|
|
184
184
|
inputUpdate();
|
|
185
185
|
pluginUpdateList.forEach(f=>f());
|
|
186
186
|
debugUpdate();
|
|
@@ -205,6 +205,7 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
|
|
|
205
205
|
time = frame++ / frameRate;
|
|
206
206
|
|
|
207
207
|
// update game and objects
|
|
208
|
+
updateCanvas();
|
|
208
209
|
inputUpdate();
|
|
209
210
|
gameUpdate();
|
|
210
211
|
pluginUpdateList.forEach(f=>f());
|
|
@@ -214,14 +215,23 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
|
|
|
214
215
|
debugUpdate();
|
|
215
216
|
gameUpdatePost();
|
|
216
217
|
inputUpdatePost();
|
|
218
|
+
|
|
219
|
+
if (debugVideoCaptureIsActive())
|
|
220
|
+
renderFrame();
|
|
217
221
|
}
|
|
218
222
|
|
|
219
223
|
// add the time smoothing back in
|
|
220
224
|
frameTimeBufferMS += deltaSmooth;
|
|
221
225
|
}
|
|
222
226
|
|
|
223
|
-
if (!
|
|
227
|
+
if (!debugVideoCaptureIsActive())
|
|
228
|
+
renderFrame();
|
|
229
|
+
requestAnimationFrame(engineUpdate);
|
|
230
|
+
|
|
231
|
+
function renderFrame()
|
|
224
232
|
{
|
|
233
|
+
if (headlessMode) return;
|
|
234
|
+
|
|
225
235
|
// render sort then render while removing destroyed objects
|
|
226
236
|
enginePreRender();
|
|
227
237
|
gameRender();
|
|
@@ -251,7 +261,6 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
|
|
|
251
261
|
}
|
|
252
262
|
drawCount = 0;
|
|
253
263
|
}
|
|
254
|
-
requestAnimationFrame(engineUpdate);
|
|
255
264
|
}
|
|
256
265
|
|
|
257
266
|
function updateCanvas()
|
|
@@ -277,6 +286,14 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
|
|
|
277
286
|
mainCanvas.height = min(innerHeight, canvasMaxSize.y);
|
|
278
287
|
}
|
|
279
288
|
|
|
289
|
+
// apply the clear color to main canvas
|
|
290
|
+
if (canvasClearColor.a > 0)
|
|
291
|
+
{
|
|
292
|
+
mainContext.fillStyle = canvasClearColor.toString();
|
|
293
|
+
mainContext.fillRect(0, 0, mainCanvasSize.x, mainCanvasSize.y);
|
|
294
|
+
mainContext.fillStyle = BLACK.toString();
|
|
295
|
+
}
|
|
296
|
+
|
|
280
297
|
// clear overlay canvas and set size
|
|
281
298
|
overlayCanvas.width = mainCanvas.width;
|
|
282
299
|
overlayCanvas.height = mainCanvas.height;
|
|
@@ -1179,7 +1196,7 @@ function debugVideoCaptureStart()
|
|
|
1179
1196
|
const chunks = [];
|
|
1180
1197
|
debugVideoCaptureTrack = stream.getVideoTracks()[0];
|
|
1181
1198
|
if (debugVideoCaptureTrack.applyConstraints)
|
|
1182
|
-
debugVideoCaptureTrack.applyConstraints({frameRate:
|
|
1199
|
+
debugVideoCaptureTrack.applyConstraints({frameRate:60}); // force 60 fps
|
|
1183
1200
|
debugVideoCapture = new MediaRecorder(stream, {mimeType:'video/webm;codecs=vp8'});
|
|
1184
1201
|
debugVideoCapture.ondataavailable = (e)=> chunks.push(e.data);
|
|
1185
1202
|
debugVideoCapture.onstop = ()=>
|
|
@@ -1401,8 +1418,11 @@ function nearestPowerOfTwo(value) { return 2**Math.ceil(Math.log2(value)); }
|
|
|
1401
1418
|
* @memberof Utilities */
|
|
1402
1419
|
function isOverlapping(posA, sizeA, posB, sizeB=vec2())
|
|
1403
1420
|
{
|
|
1404
|
-
|
|
1405
|
-
|
|
1421
|
+
const dx = (posA.x - posB.x)*2;
|
|
1422
|
+
const dy = (posA.y - posB.y)*2;
|
|
1423
|
+
const sx = sizeA.x + sizeB.x;
|
|
1424
|
+
const sy = sizeA.y + sizeB.y;
|
|
1425
|
+
return dx >= -sx && dx < sx && dy >= -sy && dy < sy;
|
|
1406
1426
|
}
|
|
1407
1427
|
|
|
1408
1428
|
/** Returns true if a line segment is intersecting an axis aligned box
|
|
@@ -2231,6 +2251,10 @@ class Timer
|
|
|
2231
2251
|
* @return {number} */
|
|
2232
2252
|
getPercent() { return this.isSet()? 1-percent(this.time - time, 0, this.setTime) : 0; }
|
|
2233
2253
|
|
|
2254
|
+
/** Get the time this timer was set to, returns 0 if not set
|
|
2255
|
+
* @return {number} */
|
|
2256
|
+
getSetTime() { return this.isSet() ? this.setTime : 0; }
|
|
2257
|
+
|
|
2234
2258
|
/** Returns this timer expressed as a string
|
|
2235
2259
|
* @return {string} */
|
|
2236
2260
|
toString() { if (debug) { return this.isSet() ? Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ) : 'unset'; }}
|
|
@@ -2276,6 +2300,11 @@ let cameraScale = 32;
|
|
|
2276
2300
|
* @memberof Settings */
|
|
2277
2301
|
let canvasColorTiles = true;
|
|
2278
2302
|
|
|
2303
|
+
/** Color to clear the canvas to before render
|
|
2304
|
+
* @type {Color}
|
|
2305
|
+
* @memberof Draw */
|
|
2306
|
+
let canvasClearColor = CLEAR_BLACK;
|
|
2307
|
+
|
|
2279
2308
|
/** The max size of the canvas, centered if window is larger
|
|
2280
2309
|
* @type {Vector2}
|
|
2281
2310
|
* @default Vector2(1920,1080)
|
|
@@ -2554,6 +2583,11 @@ function setCameraScale(scale) { cameraScale = scale; }
|
|
|
2554
2583
|
* @memberof Settings */
|
|
2555
2584
|
function setCanvasColorTiles(colorTiles) { canvasColorTiles = colorTiles; }
|
|
2556
2585
|
|
|
2586
|
+
/** Set color to clear the canvas to before render
|
|
2587
|
+
* @param {Color} color
|
|
2588
|
+
* @memberof Settings */
|
|
2589
|
+
function setCanvasClearColor(color) { canvasClearColor = color; }
|
|
2590
|
+
|
|
2557
2591
|
/** Set max size of the canvas
|
|
2558
2592
|
* @param {Vector2} size
|
|
2559
2593
|
* @memberof Settings */
|
|
@@ -2619,7 +2653,7 @@ function setGLEnable(enable)
|
|
|
2619
2653
|
glCanvas.style.visibility = enable ? 'visible' : 'hidden';
|
|
2620
2654
|
}
|
|
2621
2655
|
|
|
2622
|
-
/** Set how many sided polygons to use when drawing circles and
|
|
2656
|
+
/** Set how many sided polygons to use when drawing circles and ellipses with WebGL
|
|
2623
2657
|
* @param {number} sides
|
|
2624
2658
|
* @memberof Settings */
|
|
2625
2659
|
function setGLCircleSides(sides) { glCircleSides = sides; }
|
|
@@ -2830,7 +2864,7 @@ class EngineObject
|
|
|
2830
2864
|
/** @property {Vector2} - World space position of the object */
|
|
2831
2865
|
this.pos = pos.copy();
|
|
2832
2866
|
/** @property {Vector2} - World space width and height of the object */
|
|
2833
|
-
this.size = size;
|
|
2867
|
+
this.size = size.copy();
|
|
2834
2868
|
/** @property {Vector2} - Size of object used for drawing, uses size if not set */
|
|
2835
2869
|
this.drawSize = undefined;
|
|
2836
2870
|
/** @property {TileInfo} - Tile info to render object (undefined is untextured) */
|
|
@@ -2838,7 +2872,7 @@ class EngineObject
|
|
|
2838
2872
|
/** @property {number} - Angle to rotate the object */
|
|
2839
2873
|
this.angle = angle;
|
|
2840
2874
|
/** @property {Color} - Color to apply when rendered */
|
|
2841
|
-
this.color = color;
|
|
2875
|
+
this.color = color.copy();
|
|
2842
2876
|
/** @property {Color} - Additive color to apply when rendered */
|
|
2843
2877
|
this.additiveColor = undefined;
|
|
2844
2878
|
/** @property {boolean} - Should it flip along y axis when rendered */
|
|
@@ -2962,7 +2996,7 @@ class EngineObject
|
|
|
2962
2996
|
for (const o of engineObjectsCollide)
|
|
2963
2997
|
{
|
|
2964
2998
|
// non solid objects don't collide with each other
|
|
2965
|
-
if (!this.isSolid && !o.isSolid || o.destroyed || o.parent || o === this)
|
|
2999
|
+
if ((!this.isSolid && !o.isSolid) || o.destroyed || o.parent || o === this)
|
|
2966
3000
|
continue;
|
|
2967
3001
|
|
|
2968
3002
|
// check collision
|
|
@@ -3001,7 +3035,7 @@ class EngineObject
|
|
|
3001
3035
|
{
|
|
3002
3036
|
// push outside object collision
|
|
3003
3037
|
this.pos.y = o.pos.y + (sizeBoth.y/2 + epsilon) * sign(oldPos.y - o.pos.y);
|
|
3004
|
-
if (o.groundObject && wasMovingDown || !o.mass)
|
|
3038
|
+
if ((o.groundObject && wasMovingDown) || !o.mass)
|
|
3005
3039
|
{
|
|
3006
3040
|
// set ground object if landed on something
|
|
3007
3041
|
if (wasMovingDown)
|
|
@@ -3382,8 +3416,9 @@ class TileInfo
|
|
|
3382
3416
|
* @param {Vector2} [size=tileSizeDefault] - Size of tile in pixels
|
|
3383
3417
|
* @param {number} [textureIndex] - Texture index to use
|
|
3384
3418
|
* @param {number} [padding] - How many pixels padding around tiles
|
|
3419
|
+
* @param {number} [bleedScale] - How many pixels smaller to draw tiles
|
|
3385
3420
|
*/
|
|
3386
|
-
constructor(pos=vec2(), size=tileSizeDefault, textureIndex=0, padding=0)
|
|
3421
|
+
constructor(pos=vec2(), size=tileSizeDefault, textureIndex=0, padding=0, bleedScale=tileFixBleedScale)
|
|
3387
3422
|
{
|
|
3388
3423
|
/** @property {Vector2} - Top left corner of tile in pixels */
|
|
3389
3424
|
this.pos = pos.copy();
|
|
@@ -3395,6 +3430,8 @@ class TileInfo
|
|
|
3395
3430
|
this.padding = padding;
|
|
3396
3431
|
/** @property {TextureInfo} - The texture info for this tile */
|
|
3397
3432
|
this.textureInfo = textureInfos[this.textureIndex];
|
|
3433
|
+
/** @property {float} - Shrinks tile by this many pixels to prevent neighbors bleeding */
|
|
3434
|
+
this.bleedScale = bleedScale;
|
|
3398
3435
|
}
|
|
3399
3436
|
|
|
3400
3437
|
/** Returns a copy of this tile offset by a vector
|
|
@@ -3402,7 +3439,7 @@ class TileInfo
|
|
|
3402
3439
|
* @return {TileInfo}
|
|
3403
3440
|
*/
|
|
3404
3441
|
offset(offset)
|
|
3405
|
-
{ return new TileInfo(this.pos.add(offset), this.size, this.textureIndex); }
|
|
3442
|
+
{ return new TileInfo(this.pos.add(offset), this.size, this.textureIndex, this.padding, this.bleedScale); }
|
|
3406
3443
|
|
|
3407
3444
|
/** Returns a copy of this tile offset by a number of animation frames
|
|
3408
3445
|
* @param {number} frame - Offset to apply in animation frames
|
|
@@ -3425,6 +3462,8 @@ class TileInfo
|
|
|
3425
3462
|
this.pos = new Vector2;
|
|
3426
3463
|
this.size = new Vector2(image.width, image.height);
|
|
3427
3464
|
this.textureInfo = new TextureInfo(image, glTexture);
|
|
3465
|
+
// do not use padding or bleed
|
|
3466
|
+
this.bleedScale = this.padding = 0;
|
|
3428
3467
|
return this;
|
|
3429
3468
|
}
|
|
3430
3469
|
}
|
|
@@ -3482,6 +3521,7 @@ function drawTile(pos, size=new Vector2(1), tileInfo, color=WHITE,
|
|
|
3482
3521
|
ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
|
|
3483
3522
|
|
|
3484
3523
|
const textureInfo = tileInfo && tileInfo.textureInfo;
|
|
3524
|
+
const bleedScale = tileInfo ? tileInfo.bleedScale : 0;
|
|
3485
3525
|
if (useWebGL)
|
|
3486
3526
|
{
|
|
3487
3527
|
if (screenSpace)
|
|
@@ -3499,10 +3539,10 @@ function drawTile(pos, size=new Vector2(1), tileInfo, color=WHITE,
|
|
|
3499
3539
|
const w = tileInfo.size.x * sizeInverse.x;
|
|
3500
3540
|
const h = tileInfo.size.y * sizeInverse.y;
|
|
3501
3541
|
glSetTexture(textureInfo.glTexture);
|
|
3502
|
-
if (
|
|
3542
|
+
if (bleedScale)
|
|
3503
3543
|
{
|
|
3504
|
-
const tileImageFixBleedX = sizeInverse.x*
|
|
3505
|
-
const tileImageFixBleedY = sizeInverse.y*
|
|
3544
|
+
const tileImageFixBleedX = sizeInverse.x*bleedScale;
|
|
3545
|
+
const tileImageFixBleedY = sizeInverse.y*bleedScale;
|
|
3506
3546
|
glDraw(pos.x, pos.y, mirror ? -size.x : size.x, size.y, angle,
|
|
3507
3547
|
x + tileImageFixBleedX, y + tileImageFixBleedY,
|
|
3508
3548
|
x - tileImageFixBleedX + w, y - tileImageFixBleedY + h,
|
|
@@ -3533,7 +3573,7 @@ function drawTile(pos, size=new Vector2(1), tileInfo, color=WHITE,
|
|
|
3533
3573
|
// calculate uvs and render
|
|
3534
3574
|
const x = tileInfo.pos.x, y = tileInfo.pos.y;
|
|
3535
3575
|
const w = tileInfo.size.x, h = tileInfo.size.y;
|
|
3536
|
-
drawImageColor(context, textureInfo.image, x, y, w, h, -.5, -.5, 1, 1, color, additiveColor);
|
|
3576
|
+
drawImageColor(context, textureInfo.image, x, y, w, h, -.5, -.5, 1, 1, color, additiveColor, bleedScale);
|
|
3537
3577
|
}
|
|
3538
3578
|
else
|
|
3539
3579
|
{
|
|
@@ -4021,15 +4061,16 @@ function combineCanvases()
|
|
|
4021
4061
|
* @param {number} dHeight
|
|
4022
4062
|
* @param {Color} color
|
|
4023
4063
|
* @param {Color} [additiveColor]
|
|
4064
|
+
* @param {number} [bleedScale] - How much to shrink the source, used to fix bleeding
|
|
4024
4065
|
* @memberof Draw */
|
|
4025
|
-
function drawImageColor(context, image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, color, additiveColor)
|
|
4066
|
+
function drawImageColor(context, image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, color, additiveColor, bleedScale=0)
|
|
4026
4067
|
{
|
|
4027
4068
|
function isWhite(c) { return c.r >= 1 && c.g >= 1 && c.b >= 1; }
|
|
4028
4069
|
function isBlack(c) { return c.r <= 0 && c.g <= 0 && c.b <= 0 && c.a <= 0; }
|
|
4029
|
-
const sx2 =
|
|
4030
|
-
const sy2 =
|
|
4031
|
-
const sWidth2 = sWidth - 2*
|
|
4032
|
-
const sHeight2 = sHeight - 2*
|
|
4070
|
+
const sx2 = bleedScale;
|
|
4071
|
+
const sy2 = bleedScale;
|
|
4072
|
+
const sWidth2 = sWidth - 2*bleedScale;
|
|
4073
|
+
const sHeight2 = sHeight - 2*bleedScale;
|
|
4033
4074
|
if (!canvasColorTiles || (additiveColor ? isWhite(color.add(additiveColor)) && additiveColor.a <= 0 : isWhite(color)))
|
|
4034
4075
|
{
|
|
4035
4076
|
// white texture with no additive alpha, no need to tint
|
|
@@ -4145,7 +4186,7 @@ class FontImage
|
|
|
4145
4186
|
* @param {Vector2} pos
|
|
4146
4187
|
* @param {number} [scale=.25]
|
|
4147
4188
|
* @param {boolean} [center]
|
|
4148
|
-
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D}[context=drawContext]
|
|
4189
|
+
* @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} [context=drawContext]
|
|
4149
4190
|
*/
|
|
4150
4191
|
drawText(text, pos, scale=1, center, context=drawContext)
|
|
4151
4192
|
{
|
|
@@ -4412,6 +4453,7 @@ function inputInit()
|
|
|
4412
4453
|
document.addEventListener('wheel', onMouseWheel);
|
|
4413
4454
|
document.addEventListener('contextmenu', onContextMenu);
|
|
4414
4455
|
document.addEventListener('blur', onBlur);
|
|
4456
|
+
document.addEventListener('mouseleave', onMouseLeave);
|
|
4415
4457
|
|
|
4416
4458
|
// init touch input
|
|
4417
4459
|
if (isTouchDevice && touchInputEnable)
|
|
@@ -4470,6 +4512,12 @@ function inputInit()
|
|
|
4470
4512
|
function onMouseWheel(e) { mouseWheel = e.ctrlKey ? 0 : sign(e.deltaY); }
|
|
4471
4513
|
function onContextMenu(e) { e.preventDefault(); } // prevent right click menu
|
|
4472
4514
|
function onBlur() { inputClear(); } // reset input when focus is lost
|
|
4515
|
+
function onMouseLeave()
|
|
4516
|
+
{
|
|
4517
|
+
// set mouse position and delta when leaving canvas
|
|
4518
|
+
mousePosScreen = vec2(Infinity);
|
|
4519
|
+
mouseDeltaScreen = vec2(0);
|
|
4520
|
+
}
|
|
4473
4521
|
}
|
|
4474
4522
|
|
|
4475
4523
|
// convert a mouse or touch event position to screen space
|
|
@@ -5591,7 +5639,7 @@ class TileLayerData
|
|
|
5591
5639
|
/** @property {boolean} - If the tile should be mirrored along the x axis */
|
|
5592
5640
|
this.mirror = mirror;
|
|
5593
5641
|
/** @property {Color} - Color of the tile */
|
|
5594
|
-
this.color = color;
|
|
5642
|
+
this.color = color.copy();
|
|
5595
5643
|
}
|
|
5596
5644
|
|
|
5597
5645
|
/** Set this tile to clear, it will not be rendered */
|
|
@@ -5690,7 +5738,7 @@ class CanvasLayer extends EngineObject
|
|
|
5690
5738
|
* @param {TileInfo} [tileInfo]
|
|
5691
5739
|
* @param {Color} [color=(1,1,1,1)]
|
|
5692
5740
|
* @param {number} [angle=0]
|
|
5693
|
-
* @param {boolean} [mirror=
|
|
5741
|
+
* @param {boolean} [mirror=false] */
|
|
5694
5742
|
drawTile(pos, size=vec2(1), tileInfo, color=new Color, angle, mirror)
|
|
5695
5743
|
{
|
|
5696
5744
|
this.drawCanvas2D(pos, size, angle, mirror, (context)=>
|
|
@@ -6869,7 +6917,8 @@ function glSetTexture(texture, wrap=false)
|
|
|
6869
6917
|
return;
|
|
6870
6918
|
|
|
6871
6919
|
glFlush();
|
|
6872
|
-
|
|
6920
|
+
glActiveTexture = texture;
|
|
6921
|
+
glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture);
|
|
6873
6922
|
|
|
6874
6923
|
// set wrap mode
|
|
6875
6924
|
const wrapMode = wrap ? glContext.REPEAT : glContext.CLAMP_TO_EDGE;
|
|
@@ -6919,6 +6968,7 @@ function glCreateProgram(vsSource, fsSource)
|
|
|
6919
6968
|
}
|
|
6920
6969
|
|
|
6921
6970
|
/** Create WebGL texture from an image and init the texture settings
|
|
6971
|
+
* Restores the active texture when done
|
|
6922
6972
|
* @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} [image]
|
|
6923
6973
|
* @return {WebGLTexture}
|
|
6924
6974
|
* @memberof WebGL */
|
|
@@ -6928,30 +6978,29 @@ function glCreateTexture(image)
|
|
|
6928
6978
|
|
|
6929
6979
|
// build the texture
|
|
6930
6980
|
const texture = glContext.createTexture();
|
|
6931
|
-
|
|
6981
|
+
let mipMap = false;
|
|
6932
6982
|
if (image && image.width)
|
|
6933
6983
|
{
|
|
6934
6984
|
glSetTextureData(texture, image);
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
// use mipmap filtering
|
|
6938
|
-
glContext.generateMipmap(glContext.TEXTURE_2D);
|
|
6939
|
-
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, glContext.LINEAR_MIPMAP_LINEAR);
|
|
6940
|
-
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, glContext.LINEAR);
|
|
6941
|
-
return texture;
|
|
6942
|
-
}
|
|
6985
|
+
glContext.bindTexture(glContext.TEXTURE_2D, texture);
|
|
6986
|
+
mipMap = !tilesPixelated && isPowerOfTwo(image.width) && isPowerOfTwo(image.height);
|
|
6943
6987
|
}
|
|
6944
6988
|
else
|
|
6945
6989
|
{
|
|
6946
6990
|
// create a white texture
|
|
6947
6991
|
const whitePixel = new Uint8Array([255, 255, 255, 255]);
|
|
6992
|
+
glContext.bindTexture(glContext.TEXTURE_2D, texture);
|
|
6948
6993
|
glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, 1, 1, 0, glContext.RGBA, glContext.UNSIGNED_BYTE, whitePixel);
|
|
6949
6994
|
}
|
|
6950
6995
|
|
|
6951
6996
|
// set texture filtering
|
|
6952
|
-
const
|
|
6953
|
-
|
|
6954
|
-
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER,
|
|
6997
|
+
const magFilter = tilesPixelated ? glContext.NEAREST : glContext.LINEAR;
|
|
6998
|
+
const minFilter = mipMap ? glContext.LINEAR_MIPMAP_LINEAR : magFilter;
|
|
6999
|
+
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, magFilter);
|
|
7000
|
+
glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, minFilter);
|
|
7001
|
+
if (mipMap)
|
|
7002
|
+
glContext.generateMipmap(glContext.TEXTURE_2D);
|
|
7003
|
+
glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture); // rebind active texture
|
|
6955
7004
|
return texture;
|
|
6956
7005
|
}
|
|
6957
7006
|
|
|
@@ -6964,7 +7013,7 @@ function glDeleteTexture(texture)
|
|
|
6964
7013
|
glContext.deleteTexture(texture);
|
|
6965
7014
|
}
|
|
6966
7015
|
|
|
6967
|
-
/** Set WebGL texture data from an image
|
|
7016
|
+
/** Set WebGL texture data from an image, restores the active texture when done
|
|
6968
7017
|
* @param {WebGLTexture} texture
|
|
6969
7018
|
* @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} image
|
|
6970
7019
|
* @memberof WebGL */
|
|
@@ -6976,6 +7025,7 @@ function glSetTextureData(texture, image)
|
|
|
6976
7025
|
ASSERT(!!image && image.width > 0, 'Invalid image data.');
|
|
6977
7026
|
glContext.bindTexture(glContext.TEXTURE_2D, texture);
|
|
6978
7027
|
glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, image);
|
|
7028
|
+
glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture); // rebind active texture
|
|
6979
7029
|
}
|
|
6980
7030
|
|
|
6981
7031
|
/** Draw all sprites and clear out the buffer, called automatically by the system whenever necessary
|
|
@@ -7121,7 +7171,7 @@ function glDrawPoints(points, rgba)
|
|
|
7121
7171
|
|
|
7122
7172
|
// setup triangle strip with degenerate verts at start and end
|
|
7123
7173
|
let offset = glBatchCount * gl_INDICES_PER_POLY_VERTEX;
|
|
7124
|
-
for(let i = vertCount; i--;)
|
|
7174
|
+
for (let i = vertCount; i--;)
|
|
7125
7175
|
{
|
|
7126
7176
|
const j = clamp(i-1, 0, vertCount-3);
|
|
7127
7177
|
const point = points[j];
|
|
@@ -7149,7 +7199,7 @@ function glDrawColoredPoints(points, pointColors)
|
|
|
7149
7199
|
|
|
7150
7200
|
// setup triangle strip with degenerate verts at start and end
|
|
7151
7201
|
let offset = glBatchCount * gl_INDICES_PER_POLY_VERTEX;
|
|
7152
|
-
for(let i = vertCount; i--;)
|
|
7202
|
+
for (let i = vertCount; i--;)
|
|
7153
7203
|
{
|
|
7154
7204
|
const j = clamp(i-1, 0, vertCount-3);
|
|
7155
7205
|
const point = points[j];
|
|
@@ -7286,7 +7336,7 @@ function glPolyStrip(points)
|
|
|
7286
7336
|
while (indices.length > 3 && attempts++ < maxAttempts)
|
|
7287
7337
|
{
|
|
7288
7338
|
let foundEar = false;
|
|
7289
|
-
for (let i = indices.length;
|
|
7339
|
+
for (let i = 0; i < indices.length; i++)
|
|
7290
7340
|
{
|
|
7291
7341
|
const i0 = indices[(i + indices.length - 1) % indices.length];
|
|
7292
7342
|
const i1 = indices[i];
|
|
@@ -7323,7 +7373,7 @@ function glPolyStrip(points)
|
|
|
7323
7373
|
if (!foundEar)
|
|
7324
7374
|
{
|
|
7325
7375
|
let worstIndex = -1, worstValue = Infinity;
|
|
7326
|
-
for (let i = indices.length;
|
|
7376
|
+
for (let i = 0; i < indices.length; i++)
|
|
7327
7377
|
{
|
|
7328
7378
|
const i0 = indices[(i + indices.length - 1) % indices.length];
|
|
7329
7379
|
const i1 = indices[i];
|
|
@@ -7872,6 +7922,8 @@ class UISystemPlugin
|
|
|
7872
7922
|
this.defaultLineWidth = 4;
|
|
7873
7923
|
/** @property {number} - Default rounded rect corner radius for UI elements */
|
|
7874
7924
|
this.defaultCornerRadius = 0;
|
|
7925
|
+
/** @property {number} - Default scale to use for fitting text to object */
|
|
7926
|
+
this.defaultTextScale = .8;
|
|
7875
7927
|
/** @property {string} - Default font for UI elements */
|
|
7876
7928
|
this.defaultFont = 'arial';
|
|
7877
7929
|
/** @property {Sound} - Default sound when interactive UI element is pressed */
|
|
@@ -7884,10 +7936,15 @@ class UISystemPlugin
|
|
|
7884
7936
|
this.uiObjects = [];
|
|
7885
7937
|
/** @property {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} - Context to render UI elements to */
|
|
7886
7938
|
this.uiContext = context;
|
|
7939
|
+
/** @property {UIObject} - Top most object user is over */
|
|
7940
|
+
this.hoverObject = undefined;
|
|
7941
|
+
/** @property {UIObject} - Object user is currently interacting with */
|
|
7942
|
+
this.activeObject = undefined;
|
|
7887
7943
|
|
|
7888
7944
|
engineAddPlugin(uiUpdate, uiRender);
|
|
7889
7945
|
|
|
7890
7946
|
// setup recursive update and render
|
|
7947
|
+
// update in reverse order to detect mouse enter/leave
|
|
7891
7948
|
function uiUpdate()
|
|
7892
7949
|
{
|
|
7893
7950
|
function updateInvisibleObject(o)
|
|
@@ -7912,7 +7969,13 @@ class UISystemPlugin
|
|
|
7912
7969
|
else
|
|
7913
7970
|
updateInvisibleObject(o);
|
|
7914
7971
|
}
|
|
7915
|
-
|
|
7972
|
+
// reset hover object at start of update
|
|
7973
|
+
uiSystem.hoverObject = undefined;
|
|
7974
|
+
for (let i = uiSystem.uiObjects.length; i--;)
|
|
7975
|
+
{
|
|
7976
|
+
const o = uiSystem.uiObjects[i];
|
|
7977
|
+
o.parent || updateObject(o)
|
|
7978
|
+
}
|
|
7916
7979
|
}
|
|
7917
7980
|
function uiRender()
|
|
7918
7981
|
{
|
|
@@ -7991,10 +8054,11 @@ class UISystemPlugin
|
|
|
7991
8054
|
* @param {number} [lineWidth=uiSystem.defaultLineWidth]
|
|
7992
8055
|
* @param {Color} [lineColor=uiSystem.defaultLineColor]
|
|
7993
8056
|
* @param {string} [align]
|
|
7994
|
-
* @param {string} [font=uiSystem.defaultFont]
|
|
7995
|
-
|
|
8057
|
+
* @param {string} [font=uiSystem.defaultFont]
|
|
8058
|
+
* @param {boolean} [applyMaxWidth=true] */
|
|
8059
|
+
drawText(text, pos, size, color=uiSystem.defaultColor, lineWidth=uiSystem.defaultLineWidth, lineColor=uiSystem.defaultLineColor, align='center', font=uiSystem.defaultFont, applyMaxWidth=true)
|
|
7996
8060
|
{
|
|
7997
|
-
drawTextScreen(text, pos, size.y, color, lineWidth, lineColor, align, font, size.x, uiSystem.uiContext);
|
|
8061
|
+
drawTextScreen(text, pos, size.y, color, lineWidth, lineColor, align, font, applyMaxWidth ? size.x : undefined, uiSystem.uiContext);
|
|
7998
8062
|
}
|
|
7999
8063
|
}
|
|
8000
8064
|
|
|
@@ -8018,6 +8082,8 @@ class UIObject
|
|
|
8018
8082
|
this.size = size.copy();
|
|
8019
8083
|
/** @property {Color} - Color of the object */
|
|
8020
8084
|
this.color = uiSystem.defaultColor;
|
|
8085
|
+
/** @property {Color} - Color of the object when active, uses color if undefined */
|
|
8086
|
+
this.activeColor = undefined;
|
|
8021
8087
|
/** @property {string} - Text for this ui object */
|
|
8022
8088
|
this.text = undefined;
|
|
8023
8089
|
/** @property {Color} - Color when disabled */
|
|
@@ -8036,15 +8102,19 @@ class UIObject
|
|
|
8036
8102
|
this.cornerRadius = uiSystem.defaultCornerRadius;
|
|
8037
8103
|
/** @property {string} - Font for this objecct */
|
|
8038
8104
|
this.font = uiSystem.defaultFont;
|
|
8105
|
+
/** @property {number} - Override for text width */
|
|
8106
|
+
this.textWidth = undefined;
|
|
8039
8107
|
/** @property {number} - Override for text height */
|
|
8040
8108
|
this.textHeight = undefined;
|
|
8109
|
+
/** @property {number} - Scale text to fit in the object */
|
|
8110
|
+
this.textScale = uiSystem.defaultTextScale;
|
|
8041
8111
|
/** @property {boolean} - Should this object be drawn */
|
|
8042
8112
|
this.visible = true;
|
|
8043
8113
|
/** @property {Array<UIObject>} - A list of this object's children */
|
|
8044
8114
|
this.children = [];
|
|
8045
8115
|
/** @property {UIObject} - This object's parent, position is in parent space */
|
|
8046
8116
|
this.parent = undefined;
|
|
8047
|
-
/** @property {number} -
|
|
8117
|
+
/** @property {number} - Added size to make small buttons easier to touch on mobile devices */
|
|
8048
8118
|
this.extraTouchSize = 0;
|
|
8049
8119
|
/** @property {Sound} - Sound when interactive element is pressed */
|
|
8050
8120
|
this.soundPress = uiSystem.defaultSoundPress;
|
|
@@ -8052,12 +8122,10 @@ class UIObject
|
|
|
8052
8122
|
this.soundRelease = uiSystem.defaultSoundRelease;
|
|
8053
8123
|
/** @property {Sound} - Sound when interactive element is clicked */
|
|
8054
8124
|
this.soundClick = uiSystem.defaultSoundClick;
|
|
8055
|
-
/** @property {boolean} - Is the mouse over this element */
|
|
8056
|
-
this.mouseIsOver = false;
|
|
8057
8125
|
/** @property {boolean} - Is this element interactive */
|
|
8058
8126
|
this.interactive = false;
|
|
8059
|
-
/** @property {boolean} -
|
|
8060
|
-
this.
|
|
8127
|
+
/** @property {boolean} - Activate when dragged over with mouse held down */
|
|
8128
|
+
this.dragActivate = false;
|
|
8061
8129
|
uiSystem.uiObjects.push(this);
|
|
8062
8130
|
}
|
|
8063
8131
|
|
|
@@ -8084,15 +8152,18 @@ class UIObject
|
|
|
8084
8152
|
/** Update the object, called automatically by plugin once each frame */
|
|
8085
8153
|
update()
|
|
8086
8154
|
{
|
|
8087
|
-
const
|
|
8088
|
-
const
|
|
8155
|
+
const wasHover = this.isHoverObject();
|
|
8156
|
+
const isActive = this.isActiveObject();
|
|
8089
8157
|
const mouseDown = mouseIsDown(0);
|
|
8090
|
-
|
|
8158
|
+
const mousePress = this.dragActivate ? mouseDown : mouseWasPressed(0);
|
|
8159
|
+
if (!uiSystem.hoverObject)
|
|
8160
|
+
if (mousePress || !mouseDown || isActive)
|
|
8091
8161
|
{
|
|
8092
8162
|
const size = this.size.add(vec2(isTouchDevice && this.extraTouchSize || 0));
|
|
8093
|
-
|
|
8163
|
+
if (isOverlapping(this.pos, size, mousePosScreen))
|
|
8164
|
+
uiSystem.hoverObject = this;
|
|
8094
8165
|
}
|
|
8095
|
-
if (this.
|
|
8166
|
+
if (this.isHoverObject())
|
|
8096
8167
|
{
|
|
8097
8168
|
if (mousePress)
|
|
8098
8169
|
inputClearKey(0,0,0,1,0); // clear mouse was pressed state
|
|
@@ -8105,10 +8176,12 @@ class UIObject
|
|
|
8105
8176
|
this.onPress();
|
|
8106
8177
|
if (this.soundPress)
|
|
8107
8178
|
this.soundPress.play();
|
|
8179
|
+
if (uiSystem.activeObject && !isActive)
|
|
8180
|
+
uiSystem.activeObject.onRelease();
|
|
8181
|
+
uiSystem.activeObject = this;
|
|
8108
8182
|
}
|
|
8109
|
-
this.mouseIsHeld = true;
|
|
8110
8183
|
}
|
|
8111
|
-
if (!mouseDown &&
|
|
8184
|
+
if (!mouseDown && uiSystem.activeObject === this && this.interactive)
|
|
8112
8185
|
{
|
|
8113
8186
|
this.onClick();
|
|
8114
8187
|
if (this.soundClick)
|
|
@@ -8116,37 +8189,52 @@ class UIObject
|
|
|
8116
8189
|
}
|
|
8117
8190
|
}
|
|
8118
8191
|
}
|
|
8119
|
-
if (!mouseDown)
|
|
8192
|
+
if (isActive && (!mouseDown || !this.isHoverObject()))
|
|
8120
8193
|
{
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
this.
|
|
8124
|
-
|
|
8125
|
-
this.soundRelease.play();
|
|
8126
|
-
}
|
|
8127
|
-
if (isTouchDevice)
|
|
8128
|
-
this.mouseIsOver = false;
|
|
8129
|
-
this.mouseIsHeld = false;
|
|
8194
|
+
this.onRelease();
|
|
8195
|
+
if (this.soundRelease)
|
|
8196
|
+
this.soundRelease.play();
|
|
8197
|
+
uiSystem.activeObject = undefined;
|
|
8130
8198
|
}
|
|
8131
8199
|
|
|
8132
|
-
if (this.
|
|
8133
|
-
this.
|
|
8200
|
+
if (this.isHoverObject() !== wasHover)
|
|
8201
|
+
this.isHoverObject() ? this.onEnter() : this.onLeave();
|
|
8134
8202
|
}
|
|
8135
8203
|
|
|
8136
8204
|
/** Render the object, called automatically by plugin once each frame */
|
|
8137
8205
|
render()
|
|
8138
8206
|
{
|
|
8139
|
-
if (this.size.x
|
|
8140
|
-
|
|
8207
|
+
if (!this.size.x || !this.size.y) return;
|
|
8208
|
+
|
|
8209
|
+
const lineColor = this.interactive && this.isActiveObject() && !this.disabled ? this.color : this.lineColor;
|
|
8210
|
+
const color = this.interactive ? this.disabled ? this.disabledColor : this.isActiveObject() ? this.activeColor || this.color : this.isHoverObject() ? this.hoverColor : this.color : this.color;
|
|
8211
|
+
uiSystem.drawRect(this.pos, this.size, color, this.lineWidth, lineColor, this.cornerRadius);
|
|
8141
8212
|
}
|
|
8142
8213
|
|
|
8143
8214
|
/** Special update when object is not visible */
|
|
8144
8215
|
updateInvisible()
|
|
8145
8216
|
{
|
|
8146
8217
|
// reset input state when not visible
|
|
8147
|
-
|
|
8218
|
+
if (this.isActiveObject())
|
|
8219
|
+
uiSystem.activeObject = undefined;
|
|
8148
8220
|
}
|
|
8149
8221
|
|
|
8222
|
+
/** Get the size for text with overrides and scale
|
|
8223
|
+
* @return {Vector2}
|
|
8224
|
+
*/
|
|
8225
|
+
getTextSize()
|
|
8226
|
+
{
|
|
8227
|
+
return vec2(
|
|
8228
|
+
this.textWidth || this.textScale * this.size.x,
|
|
8229
|
+
this.textHeight || this.textScale * this.size.y);
|
|
8230
|
+
}
|
|
8231
|
+
|
|
8232
|
+
/** @return {boolean} - Is the mouse hovering over this element */
|
|
8233
|
+
isHoverObject() { return uiSystem.hoverObject === this; }
|
|
8234
|
+
|
|
8235
|
+
/** @return {boolean} - Is the mouse held onto this element */
|
|
8236
|
+
isActiveObject() { return uiSystem.activeObject === this; }
|
|
8237
|
+
|
|
8150
8238
|
/** Called when the mouse enters the object */
|
|
8151
8239
|
onEnter() {}
|
|
8152
8240
|
|
|
@@ -8194,7 +8282,7 @@ class UIText extends UIObject
|
|
|
8194
8282
|
}
|
|
8195
8283
|
render()
|
|
8196
8284
|
{
|
|
8197
|
-
const textSize =
|
|
8285
|
+
const textSize = this.getTextSize();
|
|
8198
8286
|
uiSystem.drawText(this.text, this.pos, textSize, this.textColor, this.lineWidth, this.lineColor, this.align, this.font);
|
|
8199
8287
|
}
|
|
8200
8288
|
}
|
|
@@ -8257,14 +8345,10 @@ class UIButton extends UIObject
|
|
|
8257
8345
|
}
|
|
8258
8346
|
render()
|
|
8259
8347
|
{
|
|
8260
|
-
|
|
8261
|
-
const lineColor = this.mouseIsHeld && !this.disabled ? this.color : this.lineColor;
|
|
8262
|
-
const color = this.disabled ? this.disabledColor : this.mouseIsOver ? this.hoverColor : this.color;
|
|
8263
|
-
uiSystem.drawRect(this.pos, this.size, color, this.lineWidth, lineColor, this.cornerRadius);
|
|
8348
|
+
super.render();
|
|
8264
8349
|
|
|
8265
|
-
// draw the text
|
|
8266
|
-
const
|
|
8267
|
-
const textSize = vec2(this.size.x, this.textHeight || this.size.y*textScale);
|
|
8350
|
+
// draw the text scaled to fit
|
|
8351
|
+
const textSize = this.getTextSize();
|
|
8268
8352
|
uiSystem.drawText(this.text, this.pos, textSize,
|
|
8269
8353
|
this.textColor, 0, undefined, this.align, this.font);
|
|
8270
8354
|
}
|
|
@@ -8302,8 +8386,7 @@ class UICheckbox extends UIObject
|
|
|
8302
8386
|
}
|
|
8303
8387
|
render()
|
|
8304
8388
|
{
|
|
8305
|
-
|
|
8306
|
-
uiSystem.drawRect(this.pos, this.size, color, this.lineWidth, this.lineColor, this.cornerRadius);
|
|
8389
|
+
super.render();
|
|
8307
8390
|
if (this.checked)
|
|
8308
8391
|
{
|
|
8309
8392
|
const p = this.cornerRadius / min(this.size.x, this.size.y) * 2;
|
|
@@ -8313,13 +8396,11 @@ class UICheckbox extends UIObject
|
|
|
8313
8396
|
uiSystem.drawLine(this.pos.add(s.multiply(vec2(-1,1))), this.pos.add(s.multiply(vec2(1,-1))), this.lineWidth, this.lineColor);
|
|
8314
8397
|
}
|
|
8315
8398
|
|
|
8316
|
-
// draw the text to the
|
|
8317
|
-
const
|
|
8318
|
-
const
|
|
8319
|
-
const textSize = vec2(this.size.x, this.textHeight || this.size.y*textScale);
|
|
8320
|
-
const pos = this.pos.add(vec2(this.size.x*gapScale,0));
|
|
8399
|
+
// draw the text next to the checkbox
|
|
8400
|
+
const textSize = this.getTextSize();
|
|
8401
|
+
const pos = this.pos.add(vec2(this.size.x,0));
|
|
8321
8402
|
uiSystem.drawText(this.text, pos, textSize,
|
|
8322
|
-
this.textColor, 0, undefined, 'left', this.font);
|
|
8403
|
+
this.textColor, 0, undefined, 'left', this.font, false);
|
|
8323
8404
|
}
|
|
8324
8405
|
}
|
|
8325
8406
|
|
|
@@ -8355,7 +8436,7 @@ class UIScrollbar extends UIObject
|
|
|
8355
8436
|
update()
|
|
8356
8437
|
{
|
|
8357
8438
|
super.update();
|
|
8358
|
-
if (this.
|
|
8439
|
+
if (this.isActiveObject() && this.interactive)
|
|
8359
8440
|
{
|
|
8360
8441
|
// check if value changed
|
|
8361
8442
|
const handleSize = vec2(this.size.y);
|
|
@@ -8369,12 +8450,7 @@ class UIScrollbar extends UIObject
|
|
|
8369
8450
|
}
|
|
8370
8451
|
render()
|
|
8371
8452
|
{
|
|
8372
|
-
|
|
8373
|
-
const lineColor = this.interactive && this.mouseIsHeld && !this.disabled ?
|
|
8374
|
-
this.color : this.lineColor;
|
|
8375
|
-
const color = this.disabled ? this.disabledColor :
|
|
8376
|
-
this.interactive && this.mouseIsHeld ? this.hoverColor : this.color;
|
|
8377
|
-
uiSystem.drawRect(this.pos, this.size, color, this.lineWidth, lineColor, this.cornerRadius);
|
|
8453
|
+
super.render();
|
|
8378
8454
|
|
|
8379
8455
|
// draw the scrollbar handle
|
|
8380
8456
|
const handleSize = vec2(this.size.y);
|
|
@@ -8383,12 +8459,11 @@ class UIScrollbar extends UIObject
|
|
|
8383
8459
|
const p2 = this.pos.x + handleWidth/2;
|
|
8384
8460
|
const handlePos = vec2(lerp(p1, p2, this.value), this.pos.y);
|
|
8385
8461
|
const handleColor = this.disabled ? this.disabledColor :
|
|
8386
|
-
this.interactive && this.
|
|
8462
|
+
this.interactive && this.isActiveObject() ? this.color : this.handleColor;
|
|
8387
8463
|
uiSystem.drawRect(handlePos, handleSize, handleColor, this.lineWidth, this.lineColor, this.cornerRadius);
|
|
8388
8464
|
|
|
8389
|
-
// draw the text on the scrollbar
|
|
8390
|
-
const
|
|
8391
|
-
const textSize = vec2(this.size.x, this.textHeight || this.size.y*textScale);
|
|
8465
|
+
// draw the text scaled to fit on the scrollbar
|
|
8466
|
+
const textSize = this.getTextSize();
|
|
8392
8467
|
uiSystem.drawText(this.text, this.pos, textSize,
|
|
8393
8468
|
this.textColor, 0, undefined, this.align, this.font);
|
|
8394
8469
|
}
|
|
@@ -10367,6 +10442,7 @@ export
|
|
|
10367
10442
|
cameraAngle,
|
|
10368
10443
|
cameraScale,
|
|
10369
10444
|
canvasColorTiles,
|
|
10445
|
+
canvasClearColor,
|
|
10370
10446
|
canvasMaxSize,
|
|
10371
10447
|
canvasFixedSize,
|
|
10372
10448
|
canvasPixelated,
|
|
@@ -10408,6 +10484,7 @@ export
|
|
|
10408
10484
|
setCameraAngle,
|
|
10409
10485
|
setCameraScale,
|
|
10410
10486
|
setCanvasColorTiles,
|
|
10487
|
+
setCanvasClearColor,
|
|
10411
10488
|
setCanvasMaxSize,
|
|
10412
10489
|
setCanvasFixedSize,
|
|
10413
10490
|
setCanvasPixelated,
|
|
@@ -10506,8 +10583,6 @@ export
|
|
|
10506
10583
|
MAGENTA,
|
|
10507
10584
|
|
|
10508
10585
|
// Draw
|
|
10509
|
-
textureInfos,
|
|
10510
|
-
drawCount,
|
|
10511
10586
|
tile,
|
|
10512
10587
|
TileInfo,
|
|
10513
10588
|
TextureInfo,
|
|
@@ -10518,6 +10593,8 @@ export
|
|
|
10518
10593
|
overlayCanvas,
|
|
10519
10594
|
overlayContext,
|
|
10520
10595
|
mainCanvasSize,
|
|
10596
|
+
textureInfos,
|
|
10597
|
+
drawCount,
|
|
10521
10598
|
screenToWorld,
|
|
10522
10599
|
worldToScreen,
|
|
10523
10600
|
drawTile,
|