littlejsengine 1.14.2 → 1.14.4

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.
@@ -377,10 +377,10 @@ function vec2(x=0, y) { return new Vector2(x, y === undefined ? x : y); }
377
377
  * @param {any} v
378
378
  * @return {boolean}
379
379
  * @memberof Utilities */
380
- function isVector2(v) { return v instanceof Vector2; }
380
+ function isVector2(v) { return v instanceof Vector2 && v.isValid(); }
381
381
 
382
382
  // vector2 asserts
383
- function ASSERT_VECTOR2_VALID(v) { ASSERT(isVector2(v) && v.isValid(), 'Vector2 is invalid.', v); }
383
+ function ASSERT_VECTOR2_VALID(v) { ASSERT(isVector2(v), 'Vector2 is invalid.', v); }
384
384
  function ASSERT_NUMBER_VALID(n) { ASSERT(isNumber(n), 'Number is invalid.', n); }
385
385
  function ASSERT_VECTOR2_NORMAL(v)
386
386
  {
@@ -638,10 +638,10 @@ function hsl(h, s, l, a) { return new Color().setHSLA(h, s, l, a); }
638
638
  * @param {any} c
639
639
  * @return {boolean}
640
640
  * @memberof Utilities */
641
- function isColor(c) { return c instanceof Color; }
641
+ function isColor(c) { return c instanceof Color && c.isValid(); }
642
642
 
643
643
  // color asserts
644
- function ASSERT_COLOR_VALID(c) { ASSERT(isColor(c) && c.isValid(), 'Color is invalid.', c); }
644
+ function ASSERT_COLOR_VALID(c) { ASSERT(isColor(c), 'Color is invalid.', c); }
645
645
 
646
646
  /**
647
647
  * Color object (red, green, blue, alpha) with some helpful functions
@@ -32,7 +32,7 @@ let glAntialias = true;
32
32
  let glShader, glPolyShader, glPolyMode, glAdditive, glBatchAdditive, glActiveTexture, glArrayBuffer, glGeometryBuffer, glPositionData, glColorData, glBatchCount;
33
33
 
34
34
  // WebGL internal constants
35
- const gl_ARRAY_BUFFER_SIZE = 4e5;
35
+ const gl_ARRAY_BUFFER_SIZE = 5e5;
36
36
  const gl_INDICES_PER_INSTANCE = 11;
37
37
  const gl_INSTANCE_BYTE_STRIDE = gl_INDICES_PER_INSTANCE * 4;
38
38
  const gl_MAX_INSTANCES = gl_ARRAY_BUFFER_SIZE / gl_INSTANCE_BYTE_STRIDE | 0;
@@ -126,9 +126,9 @@ function glInit()
126
126
  glContext.bufferData(glContext.ARRAY_BUFFER, geometry, glContext.STATIC_DRAW);
127
127
  }
128
128
 
129
- function glSetInstancedMode(force=false)
129
+ function glSetInstancedMode()
130
130
  {
131
- if (!glPolyMode && !force)
131
+ if (!glPolyMode)
132
132
  return;
133
133
 
134
134
  // setup instanced mode
@@ -209,7 +209,7 @@ function glPreRender()
209
209
  1, 1, 1, 0,
210
210
  p.x, p.y, 0, 1];
211
211
 
212
- // set the same matrix for both shaders
212
+ // set the same transform matrix for both shaders
213
213
  const initUniform = (program, uniform, value) =>
214
214
  {
215
215
  glContext.useProgram(program);
@@ -227,9 +227,12 @@ function glPreRender()
227
227
  glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture);
228
228
  }
229
229
 
230
- // start in instanced rendering mode with additive blending off
231
- glAdditive = glBatchAdditive = glPolyMode = false;
232
- glSetInstancedMode(true);
230
+ // start with additive blending off
231
+ glAdditive = glBatchAdditive = false;
232
+
233
+ // force it to enter instanced mode
234
+ glPolyMode = true;
235
+ glSetInstancedMode();
233
236
  }
234
237
 
235
238
  /** Clear the canvas and setup the viewport
@@ -239,7 +242,9 @@ function glClearCanvas()
239
242
  if (!glContext) return;
240
243
 
241
244
  // clear and set to same size as main canvas
242
- glContext.viewport(0, 0, glCanvas.width=drawCanvas.width, glCanvas.height=drawCanvas.height);
245
+ glCanvas.width = drawCanvas.width;
246
+ glCanvas.height = drawCanvas.height;
247
+ glContext.viewport(0, 0, glCanvas.width, glCanvas.height);
243
248
  glContext.clear(glContext.COLOR_BUFFER_BIT);
244
249
  }
245
250
 
@@ -374,15 +379,17 @@ function glFlush()
374
379
  const destBlend = glBatchAdditive ? glContext.ONE : glContext.ONE_MINUS_SRC_ALPHA;
375
380
  glContext.blendFuncSeparate(glContext.SRC_ALPHA, destBlend, glContext.ONE, destBlend);
376
381
  glContext.enable(glContext.BLEND);
377
- glContext.bufferSubData(glContext.ARRAY_BUFFER, 0, glPositionData);
382
+
383
+ const byteLength = glBatchCount *
384
+ (glPolyMode ? gl_INDICES_PER_POLY_VERTEX : gl_INDICES_PER_INSTANCE);
385
+ glContext.bufferSubData(glContext.ARRAY_BUFFER, 0, glPositionData, 0, byteLength);
378
386
 
379
387
  // draw the batch
380
388
  if (glPolyMode)
381
389
  glContext.drawArrays(glContext.TRIANGLE_STRIP, 0, glBatchCount);
382
390
  else
383
391
  glContext.drawArraysInstanced(glContext.TRIANGLE_STRIP, 0, 4, glBatchCount);
384
- if (debug || showWatermark)
385
- drawCount += glBatchCount;
392
+ drawCount += glBatchCount;
386
393
  glBatchCount = 0;
387
394
  }
388
395
  glBatchAdditive = glAdditive;
@@ -446,7 +453,7 @@ function glDraw(x, y, sizeX, sizeY, angle=0, uv0X=0, uv0Y=0, uv1X=1, uv1Y=1, rgb
446
453
  }
447
454
 
448
455
  /** Transform and add a polygon to the gl draw list
449
- * @param {Array} points - Array of Vector2 points
456
+ * @param {Array<Vector2>} points - Array of Vector2 points
450
457
  * @param {number} rgba - Color of the polygon as a 32-bit integer
451
458
  * @param {number} x
452
459
  * @param {number} y
@@ -472,7 +479,7 @@ function glDrawPointsTransform(points, rgba, x, y, sx, sy, angle, tristrip=true)
472
479
  }
473
480
 
474
481
  /** Transform and add a polygon to the gl draw list
475
- * @param {Array} points - Array of Vector2 points
482
+ * @param {Array<Vector2>} points - Array of Vector2 points
476
483
  * @param {number} rgba - Color of the polygon as a 32-bit integer
477
484
  * @param {number} lineWidth - Width of the outline
478
485
  * @param {number} x
@@ -480,61 +487,73 @@ function glDrawPointsTransform(points, rgba, x, y, sx, sy, angle, tristrip=true)
480
487
  * @param {number} sx
481
488
  * @param {number} sy
482
489
  * @param {number} angle
490
+ * @param {boolean} [wrap] - Should the outline connect the first and last points
483
491
  * @memberof WebGL */
484
- function glDrawOutlineTransform(points, rgba, lineWidth, x, y, sx, sy, angle)
492
+ function glDrawOutlineTransform(points, rgba, lineWidth, x, y, sx, sy, angle, wrap=true)
485
493
  {
486
- const outlinePoints = glMakeOutline(points, lineWidth);
494
+ const outlinePoints = glMakeOutline(points, lineWidth, wrap);
487
495
  glDrawPointsTransform(outlinePoints, rgba, x, y, sx, sy, angle, false);
488
496
  }
489
497
 
490
- /** Add a polygon to the gl draw list
491
- * @param {Array} points - Array of Vector2 points in triangle strip order
492
- * @param {number} rgba - Color of the polygon as a 32-bit integer
498
+ /** Add a list of points to the gl draw list
499
+ * @param {Array<Vector2>} points - Array of Vector2 points in tri strip order
500
+ * @param {number} rgba - Color as a 32-bit integer
493
501
  * @memberof WebGL */
494
502
  function glDrawPoints(points, rgba)
495
503
  {
496
504
  if (!glEnable || points.length < 3)
497
505
  return; // needs at least 3 points to have area
498
506
 
499
- // add 2 degenerate verts if batching with existing polys to separate them
500
- const needsBridge = glPolyMode && glBatchCount > 0;
501
- const bridgeVerts = needsBridge ? 2 : 0;
502
- const vertCount = points.length + bridgeVerts;
503
-
504
507
  // flush if there is not enough room or if different blend mode
505
- if (!glPolyMode || glBatchCount+vertCount >= gl_MAX_POLY_VERTEXES || glBatchAdditive !== glAdditive)
508
+ const vertCount = points.length + 2;
509
+ if (glBatchCount+vertCount >= gl_MAX_POLY_VERTEXES || glBatchAdditive !== glAdditive)
506
510
  glFlush();
507
511
  glSetPolyMode();
508
512
 
513
+ // setup triangle strip with degenerate verts at start and end
509
514
  let offset = glBatchCount * gl_INDICES_PER_POLY_VERTEX;
510
-
511
- // add degenerate bridge if needed (repeat last vertex of previous poly, then first of new poly)
512
- if (needsBridge)
515
+ for(let i = vertCount; i--;)
513
516
  {
514
- // repeat last vertex from previous batch (it's at offset - 3)
515
- const prevOffset = offset - 3;
516
- glPositionData[offset++] = glPositionData[prevOffset];
517
- glPositionData[offset++] = glPositionData[prevOffset + 1];
518
- glColorData[offset++] = glColorData[prevOffset + 2];
519
-
520
- // repeat first vertex of new poly
521
- glPositionData[offset++] = points[0].x;
522
- glPositionData[offset++] = points[0].y;
517
+ const j = clamp(i-1, 0, vertCount-3);
518
+ const point = points[j];
519
+ glPositionData[offset++] = point.x;
520
+ glPositionData[offset++] = point.y;
523
521
  glColorData[offset++] = rgba;
524
522
  }
523
+ glBatchCount += vertCount;
524
+ }
525
+
526
+ /** Add a list of colored points to the gl draw list
527
+ * @param {Array<Vector2>} points - Array of Vector2 points in tri strip order
528
+ * @param {Array<number>} pointColors - Array of 32-bit integer colors
529
+ * @memberof WebGL */
530
+ function glDrawColoredPoints(points, pointColors)
531
+ {
532
+ if (!glEnable || points.length < 3)
533
+ return; // needs at least 3 points to have area
525
534
 
526
- // write vertices - they're already in triangle strip order
527
- for (const point of points)
535
+ // flush if there is not enough room or if different blend mode
536
+ const vertCount = points.length + 2;
537
+ if (glBatchCount+vertCount >= gl_MAX_POLY_VERTEXES || glBatchAdditive !== glAdditive)
538
+ glFlush();
539
+ glSetPolyMode();
540
+
541
+ // setup triangle strip with degenerate verts at start and end
542
+ let offset = glBatchCount * gl_INDICES_PER_POLY_VERTEX;
543
+ for(let i = vertCount; i--;)
528
544
  {
545
+ const j = clamp(i-1, 0, vertCount-3);
546
+ const point = points[j];
547
+ const color = pointColors[j];
529
548
  glPositionData[offset++] = point.x;
530
549
  glPositionData[offset++] = point.y;
531
- glColorData[offset++] = rgba;
550
+ glColorData[offset++] = color;
532
551
  }
533
552
  glBatchCount += vertCount;
534
553
  }
535
554
 
536
555
  // WebGL internal function to convert polygon to outline triangle strip
537
- function glMakeOutline(points, width)
556
+ function glMakeOutline(points, width, wrap=true)
538
557
  {
539
558
  if (points.length < 2)
540
559
  return [];
@@ -543,12 +562,13 @@ function glMakeOutline(points, width)
543
562
  const strip = [];
544
563
  const n = points.length;
545
564
  const e = 1e-6;
565
+ const miterLimit = width*100;
546
566
  for (let i = 0; i < n; i++)
547
567
  {
548
568
  // for each vertex, calculate normal based on adjacent edges
549
- const prev = points[(i - 1 + n) % n];
569
+ const prev = points[wrap ? (i - 1 + n) % n : max(i - 1, 0)];
550
570
  const curr = points[i];
551
- const next = points[(i + 1) % n];
571
+ const next = points[wrap ? (i + 1) % n : min(i + 1, n - 1)];
552
572
 
553
573
  // direction from previous to current
554
574
  const dx1 = curr.x - prev.x;
@@ -587,8 +607,8 @@ function glMakeOutline(points, width)
587
607
  const dot = nx1 * nx + ny1 * ny;
588
608
  if (dot > e)
589
609
  {
590
- // scale normal by miter length
591
- const miterLength = 1 / dot;
610
+ // scale normal by miter length, clamped to miterLimit
611
+ const miterLength = min(1 / dot, miterLimit);
592
612
  nx *= miterLength;
593
613
  ny *= miterLength;
594
614
  }
@@ -600,7 +620,7 @@ function glMakeOutline(points, width)
600
620
  strip.push(inner);
601
621
  strip.push(outer);
602
622
  }
603
- if (strip.length > 1)
623
+ if (strip.length > 1 && wrap)
604
624
  {
605
625
  // close the loop
606
626
  strip.push(strip[0]);
@@ -635,10 +655,8 @@ function glPolyStrip(points)
635
655
  if (signedArea(points) < 0)
636
656
  points = points.reverse();
637
657
 
638
- // tolerance constants
639
- const e = 1e-10;
640
-
641
658
  // check if point is inside triangle
659
+ const e = 1e-9;
642
660
  const pointInTriangle = (p, a, b, c)=>
643
661
  {
644
662
  const c1 = cross(a, b, p);
package/copyToGithub.bat DELETED
@@ -1,28 +0,0 @@
1
- @echo off
2
- echo Copying LittleJS files to GitHub repository...
3
-
4
- REM Set the GitHub repository path (adjust this to your actual GitHub repo location)
5
- set GITHUB_PATH=C:\dev\GitHub\LittleJS
6
-
7
- REM Check if GitHub path exists
8
- if not exist "%GITHUB_PATH%" (
9
- echo Error: GitHub repository path not found: %GITHUB_PATH%
10
- echo Please update the GITHUB_PATH variable in this script
11
- pause
12
- exit /b 1
13
- )
14
-
15
- echo Copying folders and files...
16
-
17
- REM Copy folders (using /E for subdirectories, /I to create destination, /Y to overwrite)
18
- xcopy "dist" "%GITHUB_PATH%\dist\" /E /I /Y
19
- xcopy "examples" "%GITHUB_PATH%\examples\" /E /I /Y
20
- xcopy "plugins" "%GITHUB_PATH%\plugins\" /E /I /Y
21
- xcopy "src" "%GITHUB_PATH%\src\" /E /I /Y
22
-
23
- REM Copy individual files
24
- copy "jsconfig.json" "%GITHUB_PATH%\" /Y
25
- copy "package.json" "%GITHUB_PATH%\" /Y
26
- copy "reference.md" "%GITHUB_PATH%\" /Y
27
-
28
- echo Copy completed successfully!