littlejsengine 1.14.5 → 1.14.7

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.
Files changed (40) hide show
  1. package/dist/littlejs.d.ts +38 -12
  2. package/dist/littlejs.esm.js +113 -53
  3. package/dist/littlejs.esm.min.js +1 -1
  4. package/dist/littlejs.js +109 -51
  5. package/dist/littlejs.min.js +1 -1
  6. package/dist/littlejs.release.js +108 -50
  7. package/examples/box2d/game.js +1 -3
  8. package/examples/box2d/gameObjects.js +2 -2
  9. package/examples/htmlMenu/game.js +1 -1
  10. package/examples/index.html +85 -49
  11. package/examples/puzzle/game.js +1 -2
  12. package/examples/shorts/animation.js +2 -2
  13. package/examples/shorts/box2d.js +1 -0
  14. package/examples/shorts/box2dCar.js +1 -0
  15. package/examples/shorts/flappyGame.js +2 -1
  16. package/examples/shorts/helloWorld.js +2 -2
  17. package/examples/shorts/hillGlideGame.js +6 -3
  18. package/examples/shorts/maze.js +1 -0
  19. package/examples/shorts/medals.js +3 -0
  20. package/examples/shorts/music.js +3 -5
  21. package/examples/shorts/platformer.js +1 -0
  22. package/examples/shorts/shapes.js +6 -6
  23. package/examples/shorts/sound.js +1 -0
  24. package/examples/shorts/spriteAtlas.js +1 -2
  25. package/examples/shorts/tileLayer.js +1 -0
  26. package/examples/shorts/tiltedView.js +1 -1
  27. package/examples/shorts/timers.js +34 -31
  28. package/examples/shorts/topDown.js +2 -1
  29. package/examples/shorts/uiSystem.js +3 -5
  30. package/examples/stress/index.html +1 -1
  31. package/examples/uiSystem/game.js +1 -1
  32. package/package.json +1 -1
  33. package/plugins/uiSystem.js +35 -17
  34. package/src/engine.js +23 -6
  35. package/src/engineDebug.js +1 -1
  36. package/src/engineDraw.js +18 -11
  37. package/src/engineExport.js +4 -2
  38. package/src/engineSettings.js +10 -0
  39. package/src/engineUtilities.js +4 -0
  40. package/src/engineWebGL.js +18 -16
@@ -49,6 +49,8 @@ class UISystemPlugin
49
49
  this.defaultLineWidth = 4;
50
50
  /** @property {number} - Default rounded rect corner radius for UI elements */
51
51
  this.defaultCornerRadius = 0;
52
+ /** @property {number} - Default scale to use for fitting text to object */
53
+ this.defaultTextScale = .8;
52
54
  /** @property {string} - Default font for UI elements */
53
55
  this.defaultFont = 'arial';
54
56
  /** @property {Sound} - Default sound when interactive UI element is pressed */
@@ -65,6 +67,7 @@ class UISystemPlugin
65
67
  engineAddPlugin(uiUpdate, uiRender);
66
68
 
67
69
  // setup recursive update and render
70
+ // update in reverse order to detect mouse enter/leave
68
71
  function uiUpdate()
69
72
  {
70
73
  function updateInvisibleObject(o)
@@ -89,7 +92,11 @@ class UISystemPlugin
89
92
  else
90
93
  updateInvisibleObject(o);
91
94
  }
92
- uiSystem.uiObjects.forEach(o=> o.parent || updateObject(o));
95
+ for (let i = uiSystem.uiObjects.length; i--;)
96
+ {
97
+ const o = uiSystem.uiObjects[i];
98
+ o.parent || updateObject(o)
99
+ }
93
100
  }
94
101
  function uiRender()
95
102
  {
@@ -168,10 +175,11 @@ class UISystemPlugin
168
175
  * @param {number} [lineWidth=uiSystem.defaultLineWidth]
169
176
  * @param {Color} [lineColor=uiSystem.defaultLineColor]
170
177
  * @param {string} [align]
171
- * @param {string} [font=uiSystem.defaultFont] */
172
- drawText(text, pos, size, color=uiSystem.defaultColor, lineWidth=uiSystem.defaultLineWidth, lineColor=uiSystem.defaultLineColor, align='center', font=uiSystem.defaultFont)
178
+ * @param {string} [font=uiSystem.defaultFont]
179
+ * @param {boolean} [applyMaxWidth=true] */
180
+ drawText(text, pos, size, color=uiSystem.defaultColor, lineWidth=uiSystem.defaultLineWidth, lineColor=uiSystem.defaultLineColor, align='center', font=uiSystem.defaultFont, applyMaxWidth=true)
173
181
  {
174
- drawTextScreen(text, pos, size.y, color, lineWidth, lineColor, align, font, size.x, uiSystem.uiContext);
182
+ drawTextScreen(text, pos, size.y, color, lineWidth, lineColor, align, font, applyMaxWidth ? size.x : undefined, uiSystem.uiContext);
175
183
  }
176
184
  }
177
185
 
@@ -213,8 +221,12 @@ class UIObject
213
221
  this.cornerRadius = uiSystem.defaultCornerRadius;
214
222
  /** @property {string} - Font for this objecct */
215
223
  this.font = uiSystem.defaultFont;
224
+ /** @property {number} - Override for text width */
225
+ this.textWidth = undefined;
216
226
  /** @property {number} - Override for text height */
217
227
  this.textHeight = undefined;
228
+ /** @property {number} - Scale text to fit in the object */
229
+ this.textScale = uiSystem.defaultTextScale;
218
230
  /** @property {boolean} - Should this object be drawn */
219
231
  this.visible = true;
220
232
  /** @property {Array<UIObject>} - A list of this object's children */
@@ -324,6 +336,16 @@ class UIObject
324
336
  this.mouseIsOver = this.mouseIsHeld = false;
325
337
  }
326
338
 
339
+ /** Get the size for text with overrides and scale
340
+ * @return {Vector2}
341
+ */
342
+ getTextSize()
343
+ {
344
+ return vec2(
345
+ this.textWidth || this.textScale * this.size.x,
346
+ this.textHeight || this.textScale * this.size.y);
347
+ }
348
+
327
349
  /** Called when the mouse enters the object */
328
350
  onEnter() {}
329
351
 
@@ -371,7 +393,7 @@ class UIText extends UIObject
371
393
  }
372
394
  render()
373
395
  {
374
- const textSize = vec2(this.size.x, this.textHeight || this.size.y);
396
+ const textSize = this.getTextSize();
375
397
  uiSystem.drawText(this.text, this.pos, textSize, this.textColor, this.lineWidth, this.lineColor, this.align, this.font);
376
398
  }
377
399
  }
@@ -439,9 +461,8 @@ class UIButton extends UIObject
439
461
  const color = this.disabled ? this.disabledColor : this.mouseIsOver ? this.hoverColor : this.color;
440
462
  uiSystem.drawRect(this.pos, this.size, color, this.lineWidth, lineColor, this.cornerRadius);
441
463
 
442
- // draw the text
443
- const textScale = .8; // scale text to fit
444
- const textSize = vec2(this.size.x, this.textHeight || this.size.y*textScale);
464
+ // draw the text scaled to fit
465
+ const textSize = this.getTextSize();
445
466
  uiSystem.drawText(this.text, this.pos, textSize,
446
467
  this.textColor, 0, undefined, this.align, this.font);
447
468
  }
@@ -490,13 +511,11 @@ class UICheckbox extends UIObject
490
511
  uiSystem.drawLine(this.pos.add(s.multiply(vec2(-1,1))), this.pos.add(s.multiply(vec2(1,-1))), this.lineWidth, this.lineColor);
491
512
  }
492
513
 
493
- // draw the text to the right side of the checkbox
494
- const textScale = .8; // scale text to fit
495
- const gapScale = .55;
496
- const textSize = vec2(this.size.x, this.textHeight || this.size.y*textScale);
497
- const pos = this.pos.add(vec2(this.size.x*gapScale,0));
514
+ // draw the text next to the checkbox
515
+ const textSize = this.getTextSize();
516
+ const pos = this.pos.add(vec2(this.size.x,0));
498
517
  uiSystem.drawText(this.text, pos, textSize,
499
- this.textColor, 0, undefined, 'left', this.font);
518
+ this.textColor, 0, undefined, 'left', this.font, false);
500
519
  }
501
520
  }
502
521
 
@@ -563,9 +582,8 @@ class UIScrollbar extends UIObject
563
582
  this.interactive && this.mouseIsHeld ? this.color : this.handleColor;
564
583
  uiSystem.drawRect(handlePos, handleSize, handleColor, this.lineWidth, this.lineColor, this.cornerRadius);
565
584
 
566
- // draw the text on the scrollbar
567
- const textScale = .8; // scale text to fit in scrollbar
568
- const textSize = vec2(this.size.x, this.textHeight || this.size.y*textScale);
585
+ // draw the text scaled to fit on the scrollbar
586
+ const textSize = this.getTextSize();
569
587
  uiSystem.drawText(this.text, this.pos, textSize,
570
588
  this.textColor, 0, undefined, this.align, this.font);
571
589
  }
package/src/engine.js CHANGED
@@ -30,7 +30,7 @@ const engineName = 'LittleJS';
30
30
  * @type {string}
31
31
  * @default
32
32
  * @memberof Engine */
33
- const engineVersion = '1.14.5';
33
+ const engineVersion = '1.14.7';
34
34
 
35
35
  /** Frames per second to update
36
36
  * @type {number}
@@ -169,15 +169,15 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
169
169
  frameTimeBufferMS += paused ? 0 : frameTimeDeltaMS;
170
170
  if (!debugSpeedUp)
171
171
  frameTimeBufferMS = min(frameTimeBufferMS, 50); // clamp min framerate
172
- if (debugVideoCaptureIsActive())
173
- frameTimeBufferMS = 0; // no time smoothing when capturing video
174
- updateCanvas();
175
172
 
176
173
  if (paused)
177
174
  {
175
+ updateCanvas();
176
+
178
177
  // update object transforms even when paused
179
178
  for (const o of engineObjects)
180
179
  o.parent || o.updateTransforms();
180
+
181
181
  inputUpdate();
182
182
  pluginUpdateList.forEach(f=>f());
183
183
  debugUpdate();
@@ -202,6 +202,7 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
202
202
  time = frame++ / frameRate;
203
203
 
204
204
  // update game and objects
205
+ updateCanvas();
205
206
  inputUpdate();
206
207
  gameUpdate();
207
208
  pluginUpdateList.forEach(f=>f());
@@ -211,14 +212,23 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
211
212
  debugUpdate();
212
213
  gameUpdatePost();
213
214
  inputUpdatePost();
215
+
216
+ if (debugVideoCaptureIsActive())
217
+ renderFrame();
214
218
  }
215
219
 
216
220
  // add the time smoothing back in
217
221
  frameTimeBufferMS += deltaSmooth;
218
222
  }
219
223
 
220
- if (!headlessMode)
224
+ if (!debugVideoCaptureIsActive())
225
+ renderFrame();
226
+ requestAnimationFrame(engineUpdate);
227
+
228
+ function renderFrame()
221
229
  {
230
+ if (headlessMode) return;
231
+
222
232
  // render sort then render while removing destroyed objects
223
233
  enginePreRender();
224
234
  gameRender();
@@ -248,7 +258,6 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
248
258
  }
249
259
  drawCount = 0;
250
260
  }
251
- requestAnimationFrame(engineUpdate);
252
261
  }
253
262
 
254
263
  function updateCanvas()
@@ -274,6 +283,14 @@ async function engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, game
274
283
  mainCanvas.height = min(innerHeight, canvasMaxSize.y);
275
284
  }
276
285
 
286
+ // apply the clear color to main canvas
287
+ if (canvasClearColor.a > 0)
288
+ {
289
+ mainContext.fillStyle = canvasClearColor.toString();
290
+ mainContext.fillRect(0, 0, mainCanvasSize.x, mainCanvasSize.y);
291
+ mainContext.fillStyle = BLACK.toString();
292
+ }
293
+
277
294
  // clear overlay canvas and set size
278
295
  overlayCanvas.width = mainCanvas.width;
279
296
  overlayCanvas.height = mainCanvas.height;
@@ -524,7 +524,7 @@ function debugVideoCaptureStart()
524
524
  const chunks = [];
525
525
  debugVideoCaptureTrack = stream.getVideoTracks()[0];
526
526
  if (debugVideoCaptureTrack.applyConstraints)
527
- debugVideoCaptureTrack.applyConstraints({frameRate:frameRate}); // force 60 fps
527
+ debugVideoCaptureTrack.applyConstraints({frameRate:60}); // force 60 fps
528
528
  debugVideoCapture = new MediaRecorder(stream, {mimeType:'video/webm;codecs=vp8'});
529
529
  debugVideoCapture.ondataavailable = (e)=> chunks.push(e.data);
530
530
  debugVideoCapture.onstop = ()=>
package/src/engineDraw.js CHANGED
@@ -136,8 +136,9 @@ class TileInfo
136
136
  * @param {Vector2} [size=tileSizeDefault] - Size of tile in pixels
137
137
  * @param {number} [textureIndex] - Texture index to use
138
138
  * @param {number} [padding] - How many pixels padding around tiles
139
+ * @param {number} [bleedScale] - How many pixels smaller to draw tiles
139
140
  */
140
- constructor(pos=vec2(), size=tileSizeDefault, textureIndex=0, padding=0)
141
+ constructor(pos=vec2(), size=tileSizeDefault, textureIndex=0, padding=0, bleedScale=tileFixBleedScale)
141
142
  {
142
143
  /** @property {Vector2} - Top left corner of tile in pixels */
143
144
  this.pos = pos.copy();
@@ -149,6 +150,8 @@ class TileInfo
149
150
  this.padding = padding;
150
151
  /** @property {TextureInfo} - The texture info for this tile */
151
152
  this.textureInfo = textureInfos[this.textureIndex];
153
+ /** @property {float} - Shrinks tile by this many pixels to prevent neighbors bleeding */
154
+ this.bleedScale = bleedScale;
152
155
  }
153
156
 
154
157
  /** Returns a copy of this tile offset by a vector
@@ -156,7 +159,7 @@ class TileInfo
156
159
  * @return {TileInfo}
157
160
  */
158
161
  offset(offset)
159
- { return new TileInfo(this.pos.add(offset), this.size, this.textureIndex); }
162
+ { return new TileInfo(this.pos.add(offset), this.size, this.textureIndex, this.padding, this.bleedScale); }
160
163
 
161
164
  /** Returns a copy of this tile offset by a number of animation frames
162
165
  * @param {number} frame - Offset to apply in animation frames
@@ -179,6 +182,8 @@ class TileInfo
179
182
  this.pos = new Vector2;
180
183
  this.size = new Vector2(image.width, image.height);
181
184
  this.textureInfo = new TextureInfo(image, glTexture);
185
+ // do not use padding or bleed
186
+ this.bleedScale = this.padding = 0;
182
187
  return this;
183
188
  }
184
189
  }
@@ -236,6 +241,7 @@ function drawTile(pos, size=new Vector2(1), tileInfo, color=WHITE,
236
241
  ASSERT(!context || !useWebGL, 'context only supported in canvas 2D mode');
237
242
 
238
243
  const textureInfo = tileInfo && tileInfo.textureInfo;
244
+ const bleedScale = tileInfo ? tileInfo.bleedScale : 0;
239
245
  if (useWebGL)
240
246
  {
241
247
  if (screenSpace)
@@ -253,10 +259,10 @@ function drawTile(pos, size=new Vector2(1), tileInfo, color=WHITE,
253
259
  const w = tileInfo.size.x * sizeInverse.x;
254
260
  const h = tileInfo.size.y * sizeInverse.y;
255
261
  glSetTexture(textureInfo.glTexture);
256
- if (tileFixBleedScale)
262
+ if (bleedScale)
257
263
  {
258
- const tileImageFixBleedX = sizeInverse.x*tileFixBleedScale;
259
- const tileImageFixBleedY = sizeInverse.y*tileFixBleedScale;
264
+ const tileImageFixBleedX = sizeInverse.x*bleedScale;
265
+ const tileImageFixBleedY = sizeInverse.y*bleedScale;
260
266
  glDraw(pos.x, pos.y, mirror ? -size.x : size.x, size.y, angle,
261
267
  x + tileImageFixBleedX, y + tileImageFixBleedY,
262
268
  x - tileImageFixBleedX + w, y - tileImageFixBleedY + h,
@@ -287,7 +293,7 @@ function drawTile(pos, size=new Vector2(1), tileInfo, color=WHITE,
287
293
  // calculate uvs and render
288
294
  const x = tileInfo.pos.x, y = tileInfo.pos.y;
289
295
  const w = tileInfo.size.x, h = tileInfo.size.y;
290
- drawImageColor(context, textureInfo.image, x, y, w, h, -.5, -.5, 1, 1, color, additiveColor);
296
+ drawImageColor(context, textureInfo.image, x, y, w, h, -.5, -.5, 1, 1, color, additiveColor, bleedScale);
291
297
  }
292
298
  else
293
299
  {
@@ -775,15 +781,16 @@ function combineCanvases()
775
781
  * @param {number} dHeight
776
782
  * @param {Color} color
777
783
  * @param {Color} [additiveColor]
784
+ * @param {number} [bleedScale] - How much to shrink the source, used to fix bleeding
778
785
  * @memberof Draw */
779
- function drawImageColor(context, image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, color, additiveColor)
786
+ function drawImageColor(context, image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, color, additiveColor, bleedScale=0)
780
787
  {
781
788
  function isWhite(c) { return c.r >= 1 && c.g >= 1 && c.b >= 1; }
782
789
  function isBlack(c) { return c.r <= 0 && c.g <= 0 && c.b <= 0 && c.a <= 0; }
783
- const sx2 = tileFixBleedScale;
784
- const sy2 = tileFixBleedScale;
785
- const sWidth2 = sWidth - 2*tileFixBleedScale;
786
- const sHeight2 = sHeight - 2*tileFixBleedScale;
790
+ const sx2 = bleedScale;
791
+ const sy2 = bleedScale;
792
+ const sWidth2 = sWidth - 2*bleedScale;
793
+ const sHeight2 = sHeight - 2*bleedScale;
787
794
  if (!canvasColorTiles || (additiveColor ? isWhite(color.add(additiveColor)) && additiveColor.a <= 0 : isWhite(color)))
788
795
  {
789
796
  // white texture with no additive alpha, no need to tint
@@ -53,6 +53,7 @@ export
53
53
  cameraAngle,
54
54
  cameraScale,
55
55
  canvasColorTiles,
56
+ canvasClearColor,
56
57
  canvasMaxSize,
57
58
  canvasFixedSize,
58
59
  canvasPixelated,
@@ -94,6 +95,7 @@ export
94
95
  setCameraAngle,
95
96
  setCameraScale,
96
97
  setCanvasColorTiles,
98
+ setCanvasClearColor,
97
99
  setCanvasMaxSize,
98
100
  setCanvasFixedSize,
99
101
  setCanvasPixelated,
@@ -192,8 +194,6 @@ export
192
194
  MAGENTA,
193
195
 
194
196
  // Draw
195
- textureInfos,
196
- drawCount,
197
197
  tile,
198
198
  TileInfo,
199
199
  TextureInfo,
@@ -204,6 +204,8 @@ export
204
204
  overlayCanvas,
205
205
  overlayContext,
206
206
  mainCanvasSize,
207
+ textureInfos,
208
+ drawCount,
207
209
  screenToWorld,
208
210
  worldToScreen,
209
211
  drawTile,
@@ -37,6 +37,11 @@ let cameraScale = 32;
37
37
  * @memberof Settings */
38
38
  let canvasColorTiles = true;
39
39
 
40
+ /** Color to clear the canvas to before render
41
+ * @type {Color}
42
+ * @memberof Draw */
43
+ let canvasClearColor = CLEAR_BLACK;
44
+
40
45
  /** The max size of the canvas, centered if window is larger
41
46
  * @type {Vector2}
42
47
  * @default Vector2(1920,1080)
@@ -315,6 +320,11 @@ function setCameraScale(scale) { cameraScale = scale; }
315
320
  * @memberof Settings */
316
321
  function setCanvasColorTiles(colorTiles) { canvasColorTiles = colorTiles; }
317
322
 
323
+ /** Set color to clear the canvas to before render
324
+ * @param {Color} color
325
+ * @memberof Settings */
326
+ function setCanvasClearColor(color) { canvasClearColor = color; }
327
+
318
328
  /** Set max size of the canvas
319
329
  * @param {Vector2} size
320
330
  * @memberof Settings */
@@ -985,6 +985,10 @@ class Timer
985
985
  * @return {number} */
986
986
  getPercent() { return this.isSet()? 1-percent(this.time - time, 0, this.setTime) : 0; }
987
987
 
988
+ /** Get the time this timer was set to, returns 0 if not set
989
+ * @return {number} */
990
+ getSetTime() { return this.isSet() ? this.setTime : 0; }
991
+
988
992
  /** Returns this timer expressed as a string
989
993
  * @return {string} */
990
994
  toString() { if (debug) { return this.isSet() ? Math.abs(this.get()) + ' seconds ' + (this.get()<0 ? 'before' : 'after' ) : 'unset'; }}
@@ -260,7 +260,8 @@ function glSetTexture(texture, wrap=false)
260
260
  return;
261
261
 
262
262
  glFlush();
263
- glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture = texture);
263
+ glActiveTexture = texture;
264
+ glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture);
264
265
 
265
266
  // set wrap mode
266
267
  const wrapMode = wrap ? glContext.REPEAT : glContext.CLAMP_TO_EDGE;
@@ -310,6 +311,7 @@ function glCreateProgram(vsSource, fsSource)
310
311
  }
311
312
 
312
313
  /** Create WebGL texture from an image and init the texture settings
314
+ * Restores the active texture when done
313
315
  * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} [image]
314
316
  * @return {WebGLTexture}
315
317
  * @memberof WebGL */
@@ -319,30 +321,29 @@ function glCreateTexture(image)
319
321
 
320
322
  // build the texture
321
323
  const texture = glContext.createTexture();
322
- glContext.bindTexture(glContext.TEXTURE_2D, texture);
324
+ let mipMap = false;
323
325
  if (image && image.width)
324
326
  {
325
327
  glSetTextureData(texture, image);
326
- if (!tilesPixelated && isPowerOfTwo(image.width) && isPowerOfTwo(image.height))
327
- {
328
- // use mipmap filtering
329
- glContext.generateMipmap(glContext.TEXTURE_2D);
330
- glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, glContext.LINEAR_MIPMAP_LINEAR);
331
- glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, glContext.LINEAR);
332
- return texture;
333
- }
328
+ glContext.bindTexture(glContext.TEXTURE_2D, texture);
329
+ mipMap = !tilesPixelated && isPowerOfTwo(image.width) && isPowerOfTwo(image.height);
334
330
  }
335
331
  else
336
332
  {
337
333
  // create a white texture
338
334
  const whitePixel = new Uint8Array([255, 255, 255, 255]);
335
+ glContext.bindTexture(glContext.TEXTURE_2D, texture);
339
336
  glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, 1, 1, 0, glContext.RGBA, glContext.UNSIGNED_BYTE, whitePixel);
340
337
  }
341
338
 
342
339
  // set texture filtering
343
- const filter = tilesPixelated ? glContext.NEAREST : glContext.LINEAR;
344
- glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, filter);
345
- glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, filter);
340
+ const magFilter = tilesPixelated ? glContext.NEAREST : glContext.LINEAR;
341
+ const minFilter = mipMap ? glContext.LINEAR_MIPMAP_LINEAR : magFilter;
342
+ glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MAG_FILTER, magFilter);
343
+ glContext.texParameteri(glContext.TEXTURE_2D, glContext.TEXTURE_MIN_FILTER, minFilter);
344
+ if (mipMap)
345
+ glContext.generateMipmap(glContext.TEXTURE_2D);
346
+ glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture); // rebind active texture
346
347
  return texture;
347
348
  }
348
349
 
@@ -355,7 +356,7 @@ function glDeleteTexture(texture)
355
356
  glContext.deleteTexture(texture);
356
357
  }
357
358
 
358
- /** Set WebGL texture data from an image
359
+ /** Set WebGL texture data from an image, restores the active texture when done
359
360
  * @param {WebGLTexture} texture
360
361
  * @param {HTMLImageElement|HTMLCanvasElement|OffscreenCanvas} image
361
362
  * @memberof WebGL */
@@ -367,6 +368,7 @@ function glSetTextureData(texture, image)
367
368
  ASSERT(!!image && image.width > 0, 'Invalid image data.');
368
369
  glContext.bindTexture(glContext.TEXTURE_2D, texture);
369
370
  glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, image);
371
+ glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture); // rebind active texture
370
372
  }
371
373
 
372
374
  /** Draw all sprites and clear out the buffer, called automatically by the system whenever necessary
@@ -512,7 +514,7 @@ function glDrawPoints(points, rgba)
512
514
 
513
515
  // setup triangle strip with degenerate verts at start and end
514
516
  let offset = glBatchCount * gl_INDICES_PER_POLY_VERTEX;
515
- for(let i = vertCount; i--;)
517
+ for (let i = vertCount; i--;)
516
518
  {
517
519
  const j = clamp(i-1, 0, vertCount-3);
518
520
  const point = points[j];
@@ -540,7 +542,7 @@ function glDrawColoredPoints(points, pointColors)
540
542
 
541
543
  // setup triangle strip with degenerate verts at start and end
542
544
  let offset = glBatchCount * gl_INDICES_PER_POLY_VERTEX;
543
- for(let i = vertCount; i--;)
545
+ for (let i = vertCount; i--;)
544
546
  {
545
547
  const j = clamp(i-1, 0, vertCount-3);
546
548
  const point = points[j];