melonjs 10.7.1 → 10.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +29 -23
  3. package/dist/melonjs.js +2220 -1070
  4. package/dist/melonjs.min.js +4 -4
  5. package/dist/melonjs.module.d.ts +1395 -485
  6. package/dist/melonjs.module.js +2244 -1131
  7. package/package.json +17 -14
  8. package/src/camera/camera2d.js +1 -1
  9. package/src/entity/entity.js +6 -7
  10. package/src/game.js +2 -2
  11. package/src/geometries/ellipse.js +20 -21
  12. package/src/geometries/line.js +7 -7
  13. package/src/geometries/path2d.js +319 -0
  14. package/src/geometries/poly.js +27 -27
  15. package/src/geometries/rectangle.js +19 -19
  16. package/src/geometries/roundrect.js +164 -0
  17. package/src/index.js +12 -2
  18. package/src/input/gamepad.js +2 -2
  19. package/src/input/pointerevent.js +1 -1
  20. package/src/lang/deprecated.js +8 -6
  21. package/src/level/tiled/TMXLayer.js +1 -1
  22. package/src/level/tiled/TMXObject.js +9 -12
  23. package/src/level/tiled/TMXTileMap.js +23 -4
  24. package/src/level/tiled/TMXUtils.js +1 -1
  25. package/src/level/tiled/renderer/TMXHexagonalRenderer.js +1 -1
  26. package/src/level/tiled/renderer/TMXIsometricRenderer.js +1 -1
  27. package/src/level/tiled/renderer/TMXOrthogonalRenderer.js +1 -1
  28. package/src/level/tiled/renderer/TMXRenderer.js +1 -1
  29. package/src/level/tiled/renderer/TMXStaggeredRenderer.js +1 -1
  30. package/src/loader/loader.js +4 -4
  31. package/src/loader/loadingscreen.js +17 -6
  32. package/src/math/color.js +6 -5
  33. package/src/math/matrix2.js +1 -1
  34. package/src/math/matrix3.js +1 -1
  35. package/src/math/observable_vector2.js +1 -1
  36. package/src/math/observable_vector3.js +1 -1
  37. package/src/math/vector2.js +1 -1
  38. package/src/math/vector3.js +1 -1
  39. package/src/particles/emitter.js +34 -26
  40. package/src/particles/particle.js +3 -2
  41. package/src/physics/body.js +67 -51
  42. package/src/physics/bounds.js +8 -9
  43. package/src/physics/world.js +1 -1
  44. package/src/polyfill/index.js +1 -0
  45. package/src/polyfill/roundrect.js +235 -0
  46. package/src/renderable/GUI.js +5 -5
  47. package/src/renderable/collectable.js +9 -2
  48. package/src/renderable/colorlayer.js +1 -1
  49. package/src/renderable/container.js +27 -27
  50. package/src/renderable/imagelayer.js +3 -3
  51. package/src/renderable/light2d.js +115 -0
  52. package/src/renderable/renderable.js +23 -22
  53. package/src/renderable/sprite.js +15 -16
  54. package/src/renderable/trigger.js +10 -4
  55. package/src/state/stage.js +73 -3
  56. package/src/state/state.js +1 -1
  57. package/src/system/device.js +10 -8
  58. package/src/system/pooling.js +156 -149
  59. package/src/text/bitmaptext.js +1 -1
  60. package/src/text/text.js +14 -18
  61. package/src/utils/utils.js +2 -2
  62. package/src/video/canvas/canvas_renderer.js +144 -81
  63. package/src/video/renderer.js +64 -37
  64. package/src/video/{texture.js → texture/atlas.js} +8 -8
  65. package/src/video/{texture_cache.js → texture/cache.js} +4 -4
  66. package/src/video/texture/canvas_texture.js +87 -0
  67. package/src/video/webgl/glshader.js +29 -193
  68. package/src/video/webgl/utils/attributes.js +16 -0
  69. package/src/video/webgl/utils/precision.js +11 -0
  70. package/src/video/webgl/utils/program.js +58 -0
  71. package/src/video/webgl/utils/string.js +16 -0
  72. package/src/video/webgl/utils/uniforms.js +87 -0
  73. package/src/video/webgl/webgl_compositor.js +1 -14
  74. package/src/video/webgl/webgl_renderer.js +191 -231
@@ -1,14 +1,13 @@
1
1
  import Color from "./../../math/color.js";
2
- import Vector2d from "./../../math/vector2.js";
3
2
  import Matrix2d from "./../../math/matrix2.js";
4
3
  import WebGLCompositor from "./webgl_compositor.js";
5
4
  import Renderer from "./../renderer.js";
6
- import TextureCache from "./../texture_cache.js";
7
- import { TextureAtlas, createAtlas } from "./../texture.js";
5
+ import TextureCache from "./../texture/cache.js";
6
+ import { TextureAtlas, createAtlas } from "./../texture/atlas.js";
8
7
  import { createCanvas, renderer } from "./../video.js";
9
8
  import * as event from "./../../system/event.js";
10
- import * as pool from "./../../system/pooling.js";
11
- import { isPowerOfTwo, nextPowerOfTwo, TAU } from "./../../math/math.js";
9
+ import pool from "./../../system/pooling.js";
10
+ import { isPowerOfTwo, nextPowerOfTwo } from "./../../math/math.js";
12
11
 
13
12
 
14
13
  /**
@@ -41,7 +40,7 @@ class WebGLRenderer extends Renderer {
41
40
  /**
42
41
  * The WebGL version used by this renderer (1 or 2)
43
42
  * @name WebGLVersion
44
- * @memberof WebGLRenderer
43
+ * @memberof WebGLRenderer#
45
44
  * @type {number}
46
45
  * @default 1
47
46
  * @readonly
@@ -51,7 +50,7 @@ class WebGLRenderer extends Renderer {
51
50
  /**
52
51
  * The vendor string of the underlying graphics driver.
53
52
  * @name GPUVendor
54
- * @memberof WebGLRenderer
53
+ * @memberof WebGLRenderer#
55
54
  * @type {string}
56
55
  * @default null
57
56
  * @readonly
@@ -61,7 +60,7 @@ class WebGLRenderer extends Renderer {
61
60
  /**
62
61
  * The renderer string of the underlying graphics driver.
63
62
  * @name GPURenderer
64
- * @memberof WebGLRenderer
63
+ * @memberof WebGLRenderer#
65
64
  * @type {string}
66
65
  * @default null
67
66
  * @readonly
@@ -72,14 +71,14 @@ class WebGLRenderer extends Renderer {
72
71
  * The WebGL context
73
72
  * @name gl
74
73
  * @memberof WebGLRenderer
75
- * type {WebGLRenderingContext}
74
+ * @type {WebGLRenderingContext}
76
75
  */
77
76
  this.context = this.gl = this.getContextGL(this.getScreenCanvas(), options.transparent);
78
77
 
79
78
  /**
80
79
  * Maximum number of texture unit supported under the current context
81
80
  * @name maxTextures
82
- * @memberof WebGLRenderer
81
+ * @memberof WebGLRenderer#
83
82
  * @type {number}
84
83
  * @readonly
85
84
  */
@@ -105,16 +104,6 @@ class WebGLRenderer extends Renderer {
105
104
  */
106
105
  this._blendStack = [];
107
106
 
108
- /**
109
- * @ignore
110
- */
111
- this._glPoints = [
112
- new Vector2d(),
113
- new Vector2d(),
114
- new Vector2d(),
115
- new Vector2d()
116
- ];
117
-
118
107
  /**
119
108
  * The current transformation matrix used for transformations on the overall scene
120
109
  * @name currentTransform
@@ -134,7 +123,7 @@ class WebGLRenderer extends Renderer {
134
123
  /**
135
124
  * The list of active compositors
136
125
  * @name compositors
137
- * @type {Map}
126
+ * @type {Map<WebGLCompositor>}
138
127
  * @memberof WebGLRenderer#
139
128
  */
140
129
  this.compositors = new Map();
@@ -182,7 +171,7 @@ class WebGLRenderer extends Renderer {
182
171
  /**
183
172
  * Reset context state
184
173
  * @name reset
185
- * @memberof WebGLRenderer.prototype
174
+ * @memberof WebGLRenderer
186
175
  * @function
187
176
  */
188
177
  reset() {
@@ -209,7 +198,7 @@ class WebGLRenderer extends Renderer {
209
198
  * @name setCompositor
210
199
  * @function
211
200
  * @param {WebGLCompositor|string} compositor a compositor name or instance
212
- * @memberof WebGLRenderer.prototype
201
+ * @memberof WebGLRenderer
213
202
  * @function
214
203
  */
215
204
  setCompositor(compositor = "default") {
@@ -235,7 +224,7 @@ class WebGLRenderer extends Renderer {
235
224
  /**
236
225
  * Reset the gl transform to identity
237
226
  * @name resetTransform
238
- * @memberof WebGLRenderer.prototype
227
+ * @memberof WebGLRenderer
239
228
  * @function
240
229
  */
241
230
  resetTransform() {
@@ -282,7 +271,7 @@ class WebGLRenderer extends Renderer {
282
271
  /**
283
272
  * Create a pattern with the specified repetition
284
273
  * @name createPattern
285
- * @memberof WebGLRenderer.prototype
274
+ * @memberof WebGLRenderer
286
275
  * @function
287
276
  * @param {Image} image Source image
288
277
  * @param {string} repeat Define how the pattern should be repeated
@@ -315,7 +304,7 @@ class WebGLRenderer extends Renderer {
315
304
  /**
316
305
  * Flush the compositor to the frame buffer
317
306
  * @name flush
318
- * @memberof WebGLRenderer.prototype
307
+ * @memberof WebGLRenderer
319
308
  * @function
320
309
  */
321
310
  flush() {
@@ -325,7 +314,7 @@ class WebGLRenderer extends Renderer {
325
314
  /**
326
315
  * set/change the current projection matrix (WebGL only)
327
316
  * @name setProjection
328
- * @memberof WebGLRenderer.prototype
317
+ * @memberof WebGLRenderer
329
318
  * @function
330
319
  * @param {Matrix3d} matrix
331
320
  */
@@ -337,7 +326,7 @@ class WebGLRenderer extends Renderer {
337
326
  /**
338
327
  * Clears the gl context with the given color.
339
328
  * @name clearColor
340
- * @memberof WebGLRenderer.prototype
329
+ * @memberof WebGLRenderer
341
330
  * @function
342
331
  * @param {Color|string} [color="#000000"] CSS color.
343
332
  * @param {boolean} [opaque=false] Allow transparency [default] or clear the surface completely [true]
@@ -365,7 +354,7 @@ class WebGLRenderer extends Renderer {
365
354
  /**
366
355
  * Erase the pixels in the given rectangular area by setting them to transparent black (rgba(0,0,0,0)).
367
356
  * @name clearRect
368
- * @memberof WebGLRenderer.prototype
357
+ * @memberof WebGLRenderer
369
358
  * @function
370
359
  * @param {number} x x axis of the coordinate for the rectangle starting point.
371
360
  * @param {number} y y axis of the coordinate for the rectangle starting point.
@@ -415,7 +404,7 @@ class WebGLRenderer extends Renderer {
415
404
  /**
416
405
  * Draw an image to the gl context
417
406
  * @name drawImage
418
- * @memberof WebGLRenderer.prototype
407
+ * @memberof WebGLRenderer
419
408
  * @function
420
409
  * @param {Image} image An element to draw into the context. The specification permits any canvas image source (CanvasImageSource), specifically, a CSSImageValue, an HTMLImageElement, an SVGImageElement, an HTMLVideoElement, an HTMLCanvasElement, an ImageBitmap, or an OffscreenCanvas.
421
410
  * @param {number} sx The X coordinate of the top left corner of the sub-rectangle of the source image to draw into the destination context.
@@ -468,7 +457,7 @@ class WebGLRenderer extends Renderer {
468
457
  /**
469
458
  * Draw a pattern within the given rectangle.
470
459
  * @name drawPattern
471
- * @memberof WebGLRenderer.prototype
460
+ * @memberof WebGLRenderer
472
461
  * @function
473
462
  * @param {TextureAtlas} pattern Pattern object
474
463
  * @param {number} x
@@ -486,7 +475,7 @@ class WebGLRenderer extends Renderer {
486
475
  /**
487
476
  * return a reference to the screen canvas corresponding WebGL Context
488
477
  * @name getScreenContext
489
- * @memberof WebGLRenderer.prototype
478
+ * @memberof WebGLRenderer
490
479
  * @function
491
480
  * @returns {WebGLRenderingContext}
492
481
  */
@@ -497,7 +486,7 @@ class WebGLRenderer extends Renderer {
497
486
  /**
498
487
  * Returns the WebGL Context object of the given Canvas
499
488
  * @name getContextGL
500
- * @memberof WebGLRenderer.prototype
489
+ * @memberof WebGLRenderer
501
490
  * @function
502
491
  * @param {HTMLCanvasElement} canvas
503
492
  * @param {boolean} [transparent=true] use false to disable transparency
@@ -555,7 +544,7 @@ class WebGLRenderer extends Renderer {
555
544
  * Returns the WebGLContext instance for the renderer
556
545
  * return a reference to the system 2d Context
557
546
  * @name getContext
558
- * @memberof WebGLRenderer.prototype
547
+ * @memberof WebGLRenderer
559
548
  * @function
560
549
  * @returns {WebGLRenderingContext}
561
550
  */
@@ -576,7 +565,7 @@ class WebGLRenderer extends Renderer {
576
565
  * <img src="images/screen-blendmode.png" width="510"/> <br>
577
566
  * @name setBlendMode
578
567
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
579
- * @memberof WebGLRenderer.prototype
568
+ * @memberof WebGLRenderer
580
569
  * @function
581
570
  * @param {string} [mode="normal"] blend mode : "normal", "multiply", "lighter", "additive", "screen"
582
571
  * @param {WebGLRenderingContext} [gl]
@@ -627,7 +616,7 @@ class WebGLRenderer extends Renderer {
627
616
  /**
628
617
  * restores the canvas context
629
618
  * @name restore
630
- * @memberof WebGLRenderer.prototype
619
+ * @memberof WebGLRenderer
631
620
  * @function
632
621
  */
633
622
  restore() {
@@ -663,7 +652,7 @@ class WebGLRenderer extends Renderer {
663
652
  /**
664
653
  * saves the canvas context
665
654
  * @name save
666
- * @memberof WebGLRenderer.prototype
655
+ * @memberof WebGLRenderer
667
656
  * @function
668
657
  */
669
658
  save() {
@@ -681,7 +670,7 @@ class WebGLRenderer extends Renderer {
681
670
  /**
682
671
  * rotates the uniform matrix
683
672
  * @name rotate
684
- * @memberof WebGLRenderer.prototype
673
+ * @memberof WebGLRenderer
685
674
  * @function
686
675
  * @param {number} angle in radians
687
676
  */
@@ -692,7 +681,7 @@ class WebGLRenderer extends Renderer {
692
681
  /**
693
682
  * scales the uniform matrix
694
683
  * @name scale
695
- * @memberof WebGLRenderer.prototype
684
+ * @memberof WebGLRenderer
696
685
  * @function
697
686
  * @param {number} x
698
687
  * @param {number} y
@@ -713,7 +702,7 @@ class WebGLRenderer extends Renderer {
713
702
  /**
714
703
  * Set the global alpha
715
704
  * @name setGlobalAlpha
716
- * @memberof WebGLRenderer.prototype
705
+ * @memberof WebGLRenderer
717
706
  * @function
718
707
  * @param {number} alpha 0.0 to 1.0 values accepted.
719
708
  */
@@ -721,11 +710,22 @@ class WebGLRenderer extends Renderer {
721
710
  this.currentColor.alpha = alpha;
722
711
  }
723
712
 
713
+ /**
714
+ * Return the global alpha
715
+ * @name getGlobalAlpha
716
+ * @memberof WebGLRenderer
717
+ * @function
718
+ * @returns {number} global alpha value
719
+ */
720
+ getGlobalAlpha() {
721
+ return this.currentColor.alpha;
722
+ }
723
+
724
724
  /**
725
725
  * Set the current fill & stroke style color.
726
726
  * By default, or upon reset, the value is set to #000000.
727
727
  * @name setColor
728
- * @memberof WebGLRenderer.prototype
728
+ * @memberof WebGLRenderer
729
729
  * @function
730
730
  * @param {Color|string} color css color string.
731
731
  */
@@ -738,7 +738,7 @@ class WebGLRenderer extends Renderer {
738
738
  /**
739
739
  * Set the line width
740
740
  * @name setLineWidth
741
- * @memberof WebGLRenderer.prototype
741
+ * @memberof WebGLRenderer
742
742
  * @function
743
743
  * @param {number} width Line width
744
744
  */
@@ -749,7 +749,7 @@ class WebGLRenderer extends Renderer {
749
749
  /**
750
750
  * Stroke an arc at the specified coordinates with given radius, start and end points
751
751
  * @name strokeArc
752
- * @memberof WebGLRenderer.prototype
752
+ * @memberof WebGLRenderer
753
753
  * @function
754
754
  * @param {number} x arc center point x-axis
755
755
  * @param {number} y arc center point y-axis
@@ -759,41 +759,25 @@ class WebGLRenderer extends Renderer {
759
759
  * @param {boolean} [antiClockwise=false] draw arc anti-clockwise
760
760
  * @param {boolean} [fill=false]
761
761
  */
762
- strokeArc(x, y, radius, start, end, antiClockwise = false, fill) {
763
- if (fill === true ) {
764
- this.fillArc(x, y, radius, start, end, antiClockwise);
762
+ strokeArc(x, y, radius, start, end, antiClockwise = false, fill = false) {
763
+ if (this.getGlobalAlpha() < 1 / 255) {
764
+ // Fast path: don't draw fully transparent
765
+ return;
766
+ }
767
+ this.path2D.beginPath();
768
+ this.path2D.arc(x, y, radius, start, end, antiClockwise);
769
+ if (fill === false) {
770
+ this.currentCompositor.drawVertices(this.gl.LINE_STRIP, this.path2D.points);
765
771
  } else {
766
- // XXX to be optimzed using a specific shader
767
- var points = this._glPoints;
768
- var i, len = Math.floor(24 * Math.sqrt(radius * 2));
769
- var theta = (end - start) / (len * 2);
770
- var theta2 = theta * 2;
771
- var cos_theta = Math.cos(theta);
772
- var sin_theta = Math.sin(theta);
773
-
774
- // Grow internal points buffer if necessary
775
- for (i = points.length; i < len + 1; i++) {
776
- points.push(new Vector2d());
777
- }
778
-
779
- // calculate and draw all segments
780
- for (i = 0; i < len; i++) {
781
- var angle = ((theta) + start + (theta2 * i));
782
- var cos = Math.cos(angle);
783
- var sin = -Math.sin(angle);
784
-
785
- points[i].x = x + (((cos_theta * cos) + (sin_theta * sin)) * radius);
786
- points[i].y = y + (((cos_theta * -sin) + (sin_theta * cos)) * radius);
787
- }
788
- // batch draw all lines
789
- this.currentCompositor.drawVertices(this.gl.LINE_STRIP, points, len);
772
+ this.path2D.closePath();
773
+ this.currentCompositor.drawVertices(this.gl.TRIANGLES, this.path2D.triangulatePath());
790
774
  }
791
775
  }
792
776
 
793
777
  /**
794
778
  * Fill an arc at the specified coordinates with given radius, start and end points
795
779
  * @name fillArc
796
- * @memberof WebGLRenderer.prototype
780
+ * @memberof WebGLRenderer
797
781
  * @function
798
782
  * @param {number} x arc center point x-axis
799
783
  * @param {number} y arc center point y-axis
@@ -802,41 +786,14 @@ class WebGLRenderer extends Renderer {
802
786
  * @param {number} end end angle in radians
803
787
  * @param {boolean} [antiClockwise=false] draw arc anti-clockwise
804
788
  */
805
- fillArc(x, y, radius, start, end /*, antiClockwise = false*/) {
806
- // XXX to be optimzed using a specific shader
807
- var points = this._glPoints;
808
- var i, index = 0;
809
- var len = Math.floor(24 * Math.sqrt(radius * 2));
810
- var theta = (end - start) / (len * 2);
811
- var theta2 = theta * 2;
812
- var cos_theta = Math.cos(theta);
813
- var sin_theta = Math.sin(theta);
814
-
815
- // Grow internal points buffer if necessary
816
- for (i = points.length; i < len * 2; i++) {
817
- points.push(new Vector2d());
818
- }
819
-
820
- // calculate and draw all segments
821
- for (i = 0; i < len - 1; i++) {
822
- var angle = ((theta) + start + (theta2 * i));
823
- var cos = Math.cos(angle);
824
- var sin = -Math.sin(angle);
825
-
826
- points[index++].set(x, y);
827
- points[index++].set(
828
- x - (((cos_theta * cos) + (sin_theta * sin)) * radius),
829
- y - (((cos_theta * -sin) + (sin_theta * cos)) * radius)
830
- );
831
- }
832
- // batch draw all triangles
833
- this.currentCompositor.drawVertices(this.gl.TRIANGLE_STRIP, points, index);
789
+ fillArc(x, y, radius, start, end, antiClockwise = false) {
790
+ this.strokeArc(x, y, radius, start, end, antiClockwise, true);
834
791
  }
835
792
 
836
793
  /**
837
794
  * Stroke an ellipse at the specified coordinates with given radius
838
795
  * @name strokeEllipse
839
- * @memberof WebGLRenderer.prototype
796
+ * @memberof WebGLRenderer
840
797
  * @function
841
798
  * @param {number} x ellipse center point x-axis
842
799
  * @param {number} y ellipse center point y-axis
@@ -845,35 +802,24 @@ class WebGLRenderer extends Renderer {
845
802
  * @param {boolean} [fill=false] also fill the shape with the current color if true
846
803
  */
847
804
  strokeEllipse(x, y, w, h, fill = false) {
848
- if (fill === true ) {
849
- this.fillEllipse(x, y, w, h);
805
+ if (this.getGlobalAlpha() < 1 / 255) {
806
+ // Fast path: don't draw fully transparent
807
+ return;
808
+ }
809
+ this.path2D.beginPath();
810
+ this.path2D.ellipse(x, y, w, h, 0, 0, 360);
811
+ this.path2D.closePath();
812
+ if (fill === false) {
813
+ this.currentCompositor.drawVertices(this.gl.LINE_LOOP, this.path2D.points);
850
814
  } else {
851
- // XXX to be optimzed using a specific shader
852
- var len = Math.floor(24 * Math.sqrt(w)) ||
853
- Math.floor(12 * Math.sqrt(w + h));
854
- var segment = (TAU) / len;
855
- var points = this._glPoints,
856
- i;
857
-
858
- // Grow internal points buffer if necessary
859
- for (i = points.length; i < len; i++) {
860
- points.push(new Vector2d());
861
- }
862
-
863
- // calculate and draw all segments
864
- for (i = 0; i < len; i++) {
865
- points[i].x = x + (Math.sin(segment * -i) * w);
866
- points[i].y = y + (Math.cos(segment * -i) * h);
867
- }
868
- // batch draw all lines
869
- this.currentCompositor.drawVertices(this.gl.LINE_LOOP, points, len);
815
+ this.currentCompositor.drawVertices(this.gl.TRIANGLES, this.path2D.triangulatePath());
870
816
  }
871
817
  }
872
818
 
873
819
  /**
874
820
  * Fill an ellipse at the specified coordinates with given radius
875
821
  * @name fillEllipse
876
- * @memberof WebGLRenderer.prototype
822
+ * @memberof WebGLRenderer
877
823
  * @function
878
824
  * @param {number} x ellipse center point x-axis
879
825
  * @param {number} y ellipse center point y-axis
@@ -881,34 +827,13 @@ class WebGLRenderer extends Renderer {
881
827
  * @param {number} h vertical radius of the ellipse
882
828
  */
883
829
  fillEllipse(x, y, w, h) {
884
- // XXX to be optimzed using a specific shader
885
- var len = Math.floor(24 * Math.sqrt(w)) ||
886
- Math.floor(12 * Math.sqrt(w + h));
887
- var segment = (TAU) / len;
888
- var points = this._glPoints;
889
- var index = 0, i;
890
-
891
- // Grow internal points buffer if necessary
892
- for (i = points.length; i < (len + 1) * 2; i++) {
893
- points.push(new Vector2d());
894
- }
895
-
896
- // draw all vertices vertex coordinates
897
- for (i = 0; i < len + 1; i++) {
898
- points[index++].set(x, y);
899
- points[index++].set(
900
- x + (Math.sin(segment * i) * w),
901
- y + (Math.cos(segment * i) * h)
902
- );
903
- }
904
- // batch draw all triangles
905
- this.currentCompositor.drawVertices(this.gl.TRIANGLE_STRIP, points, index);
830
+ this.strokeEllipse(x, y, w, h, false);
906
831
  }
907
832
 
908
833
  /**
909
834
  * Stroke a line of the given two points
910
835
  * @name strokeLine
911
- * @memberof WebGLRenderer.prototype
836
+ * @memberof WebGLRenderer
912
837
  * @function
913
838
  * @param {number} startX the start x coordinate
914
839
  * @param {number} startY the start y coordinate
@@ -916,19 +841,21 @@ class WebGLRenderer extends Renderer {
916
841
  * @param {number} endY the end y coordinate
917
842
  */
918
843
  strokeLine(startX, startY, endX, endY) {
919
- var points = this._glPoints;
920
- points[0].x = startX;
921
- points[0].y = startY;
922
- points[1].x = endX;
923
- points[1].y = endY;
924
- this.currentCompositor.drawVertices(this.gl.LINE_STRIP, points, 2);
844
+ if (this.getGlobalAlpha() < 1 / 255) {
845
+ // Fast path: don't draw fully transparent
846
+ return;
847
+ }
848
+ this.path2D.beginPath();
849
+ this.path2D.moveTo(startX, startY);
850
+ this.path2D.lineTo(endX, endY);
851
+ this.currentCompositor.drawVertices(this.gl.LINE_STRIP, this.path2D.points);
925
852
  }
926
853
 
927
854
 
928
855
  /**
929
856
  * Fill a line of the given two points
930
857
  * @name fillLine
931
- * @memberof WebGLRenderer.prototype
858
+ * @memberof WebGLRenderer
932
859
  * @function
933
860
  * @param {number} startX the start x coordinate
934
861
  * @param {number} startY the start y coordinate
@@ -942,65 +869,50 @@ class WebGLRenderer extends Renderer {
942
869
  /**
943
870
  * Stroke a me.Polygon on the screen with a specified color
944
871
  * @name strokePolygon
945
- * @memberof WebGLRenderer.prototype
872
+ * @memberof WebGLRenderer
946
873
  * @function
947
874
  * @param {Polygon} poly the shape to draw
948
875
  * @param {boolean} [fill=false] also fill the shape with the current color if true
949
876
  */
950
877
  strokePolygon(poly, fill = false) {
951
- if (fill === true ) {
952
- this.fillPolygon(poly);
878
+ if (this.getGlobalAlpha() < 1 / 255) {
879
+ // Fast path: don't draw fully transparent
880
+ return;
881
+ }
882
+ this.translate(poly.pos.x, poly.pos.y);
883
+ this.path2D.beginPath();
884
+ this.path2D.moveTo(poly.points[0].x, poly.points[0].y);
885
+ var point;
886
+ for (var i = 1; i < poly.points.length; i++) {
887
+ point = poly.points[i];
888
+ this.path2D.lineTo(point.x, point.y);
889
+ }
890
+ this.path2D.lineTo(poly.points[0].x, poly.points[0].y);
891
+ this.path2D.closePath();
892
+ if (fill === false) {
893
+ this.currentCompositor.drawVertices(this.gl.LINE_LOOP, this.path2D.points);
953
894
  } else {
954
- var len = poly.points.length,
955
- points = this._glPoints,
956
- i;
957
-
958
- // Grow internal points buffer if necessary
959
- for (i = points.length; i < len; i++) {
960
- points.push(new Vector2d());
961
- }
962
-
963
- // calculate and draw all segments
964
- for (i = 0; i < len; i++) {
965
- points[i].x = poly.pos.x + poly.points[i].x;
966
- points[i].y = poly.pos.y + poly.points[i].y;
967
- }
968
- this.currentCompositor.drawVertices(this.gl.LINE_LOOP, points, len);
895
+ // draw all triangles
896
+ this.currentCompositor.drawVertices(this.gl.TRIANGLES, this.path2D.triangulatePath());
969
897
  }
898
+ this.translate(-poly.pos.x, -poly.pos.y);
970
899
  }
971
900
 
972
901
  /**
973
902
  * Fill a me.Polygon on the screen
974
903
  * @name fillPolygon
975
- * @memberof WebGLRenderer.prototype
904
+ * @memberof WebGLRenderer
976
905
  * @function
977
906
  * @param {Polygon} poly the shape to draw
978
907
  */
979
908
  fillPolygon(poly) {
980
- var points = poly.points;
981
- var glPoints = this._glPoints;
982
- var indices = poly.getIndices();
983
- var x = poly.pos.x, y = poly.pos.y;
984
- var i;
985
-
986
- // Grow internal points buffer if necessary
987
- for (i = glPoints.length; i < indices.length; i++) {
988
- glPoints.push(new Vector2d());
989
- }
990
-
991
- // calculate all vertices
992
- for (i = 0; i < indices.length; i++ ) {
993
- glPoints[i].set(x + points[indices[i]].x, y + points[indices[i]].y);
994
- }
995
-
996
- // draw all triangle
997
- this.currentCompositor.drawVertices(this.gl.TRIANGLES, glPoints, indices.length);
909
+ this.strokePolygon(poly, true);
998
910
  }
999
911
 
1000
912
  /**
1001
913
  * Draw a stroke rectangle at the specified coordinates
1002
914
  * @name strokeRect
1003
- * @memberof WebGLRenderer.prototype
915
+ * @memberof WebGLRenderer
1004
916
  * @function
1005
917
  * @param {number} x
1006
918
  * @param {number} y
@@ -1009,26 +921,23 @@ class WebGLRenderer extends Renderer {
1009
921
  * @param {boolean} [fill=false] also fill the shape with the current color if true
1010
922
  */
1011
923
  strokeRect(x, y, width, height, fill = false) {
1012
- if (fill === true ) {
1013
- this.fillRect(x, y, width, height);
924
+ if (this.getGlobalAlpha() < 1 / 255) {
925
+ // Fast path: don't draw fully transparent
926
+ return;
927
+ }
928
+ this.path2D.beginPath();
929
+ this.path2D.rect(x, y, width, height);
930
+ if (fill === false) {
931
+ this.currentCompositor.drawVertices(this.gl.LINE_LOOP, this.path2D.points);
1014
932
  } else {
1015
- var points = this._glPoints;
1016
- points[0].x = x;
1017
- points[0].y = y;
1018
- points[1].x = x + width;
1019
- points[1].y = y;
1020
- points[2].x = x + width;
1021
- points[2].y = y + height;
1022
- points[3].x = x;
1023
- points[3].y = y + height;
1024
- this.currentCompositor.drawVertices(this.gl.LINE_LOOP, points, 4);
933
+ this.currentCompositor.drawVertices(this.gl.TRIANGLES, this.path2D.triangulatePath());
1025
934
  }
1026
935
  }
1027
936
 
1028
937
  /**
1029
938
  * Draw a filled rectangle at the specified coordinates
1030
939
  * @name fillRect
1031
- * @memberof WebGLRenderer.prototype
940
+ * @memberof WebGLRenderer
1032
941
  * @function
1033
942
  * @param {number} x
1034
943
  * @param {number} y
@@ -1036,23 +945,56 @@ class WebGLRenderer extends Renderer {
1036
945
  * @param {number} height
1037
946
  */
1038
947
  fillRect(x, y, width, height) {
1039
- var glPoints = this._glPoints;
1040
- glPoints[0].x = x + width;
1041
- glPoints[0].y = y;
1042
- glPoints[1].x = x;
1043
- glPoints[1].y = y;
1044
- glPoints[2].x = x + width;
1045
- glPoints[2].y = y + height;
1046
- glPoints[3].x = x;
1047
- glPoints[3].y = y + height;
1048
- this.currentCompositor.drawVertices(this.gl.TRIANGLE_STRIP, glPoints, 4);
948
+ this.strokeRect(x, y, width, height, true);
949
+ }
950
+
951
+ /**
952
+ * Stroke a rounded rectangle at the specified coordinates
953
+ * @name strokeRoundRect
954
+ * @memberof WebGLRenderer
955
+ * @function
956
+ * @param {number} x
957
+ * @param {number} y
958
+ * @param {number} width
959
+ * @param {number} height
960
+ * @param {number} radius
961
+ * @param {boolean} [fill=false] also fill the shape with the current color if true
962
+ */
963
+ strokeRoundRect(x, y, width, height, radius, fill = false) {
964
+ if (this.getGlobalAlpha() < 1 / 255) {
965
+ // Fast path: don't draw fully transparent
966
+ return;
967
+ }
968
+ this.path2D.beginPath();
969
+ this.path2D.roundRect(x, y, width, height, radius);
970
+ if (fill === false) {
971
+ this.currentCompositor.drawVertices(this.gl.LINE_LOOP, this.path2D.points);
972
+ } else {
973
+ this.path2D.closePath();
974
+ this.currentCompositor.drawVertices(this.gl.TRIANGLES, this.path2D.triangulatePath());
975
+ }
976
+ }
977
+
978
+ /**
979
+ * Draw a rounded filled rectangle at the specified coordinates
980
+ * @name fillRoundRect
981
+ * @memberof WebGLRenderer
982
+ * @function
983
+ * @param {number} x
984
+ * @param {number} y
985
+ * @param {number} width
986
+ * @param {number} height
987
+ * @param {number} radius
988
+ */
989
+ fillRoundRect(x, y, width, height, radius) {
990
+ this.strokeRoundRect(x, y, width, height, radius, true);
1049
991
  }
1050
992
 
1051
993
  /**
1052
994
  * Reset (overrides) the renderer transformation matrix to the
1053
995
  * identity one, and then apply the given transformation matrix.
1054
996
  * @name setTransform
1055
- * @memberof WebGLRenderer.prototype
997
+ * @memberof WebGLRenderer
1056
998
  * @function
1057
999
  * @param {Matrix2d} mat2d Matrix to transform by
1058
1000
  */
@@ -1064,7 +1006,7 @@ class WebGLRenderer extends Renderer {
1064
1006
  /**
1065
1007
  * Multiply given matrix into the renderer tranformation matrix
1066
1008
  * @name transform
1067
- * @memberof WebGLRenderer.prototype
1009
+ * @memberof WebGLRenderer
1068
1010
  * @function
1069
1011
  * @param {Matrix2d} mat2d Matrix to transform by
1070
1012
  */
@@ -1082,7 +1024,7 @@ class WebGLRenderer extends Renderer {
1082
1024
  /**
1083
1025
  * Translates the uniform matrix by the given coordinates
1084
1026
  * @name translate
1085
- * @memberof WebGLRenderer.prototype
1027
+ * @memberof WebGLRenderer
1086
1028
  * @function
1087
1029
  * @param {number} x
1088
1030
  * @param {number} y
@@ -1105,7 +1047,7 @@ class WebGLRenderer extends Renderer {
1105
1047
  * and restore it (with the restore() method) any time in the future.
1106
1048
  * (<u>this is an experimental feature !</u>)
1107
1049
  * @name clipRect
1108
- * @memberof WebGLRenderer.prototype
1050
+ * @memberof WebGLRenderer
1109
1051
  * @function
1110
1052
  * @param {number} x
1111
1053
  * @param {number} y
@@ -1153,31 +1095,46 @@ class WebGLRenderer extends Renderer {
1153
1095
  * So, if the renderable is larger than the mask, only the intersecting part of the renderable will be visible.
1154
1096
  * Mask are not preserved through renderer context save and restore.
1155
1097
  * @name setMask
1156
- * @memberof WebGLRenderer.prototype
1098
+ * @memberof WebGLRenderer
1157
1099
  * @function
1158
- * @param {Rect|Polygon|Line|Ellipse} [mask] the shape defining the mask to be applied
1100
+ * @param {Rect|RoundRect|Polygon|Line|Ellipse} [mask] a shape defining the mask to be applied
1101
+ * @param {boolean} [invert=false] either the given shape should define what is visible (default) or the opposite
1159
1102
  */
1160
- setMask(mask) {
1103
+ setMask(mask, invert = false) {
1161
1104
  var gl = this.gl;
1162
1105
 
1163
1106
  // flush the compositor
1164
1107
  this.flush();
1165
1108
 
1166
- // Enable and setup GL state to write to stencil buffer
1167
- gl.enable(gl.STENCIL_TEST);
1168
- gl.clear(gl.STENCIL_BUFFER_BIT);
1109
+ if (this.maskLevel === 0) {
1110
+ // Enable and setup GL state to write to stencil buffer
1111
+ gl.enable(gl.STENCIL_TEST);
1112
+ gl.clear(gl.STENCIL_BUFFER_BIT);
1113
+
1114
+
1115
+ }
1116
+
1117
+ this.maskLevel++;
1118
+
1169
1119
  gl.colorMask(false, false, false, false);
1170
- gl.stencilFunc(gl.NOTEQUAL, 1, 1);
1120
+ gl.stencilFunc(gl.EQUAL, this.maskLevel, 1);
1171
1121
  gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE);
1172
1122
 
1123
+
1124
+ // fill the given mask shape
1173
1125
  this.fill(mask);
1174
1126
 
1175
1127
  // flush the compositor
1176
1128
  this.flush();
1177
1129
 
1178
- // Use stencil buffer to affect next rendering object
1179
1130
  gl.colorMask(true, true, true, true);
1180
- gl.stencilFunc(gl.EQUAL, 1, 1);
1131
+
1132
+ // Use stencil buffer to affect next rendering object
1133
+ if (invert === true) {
1134
+ gl.stencilFunc(gl.EQUAL, this.maskLevel + 1, 1);
1135
+ } else {
1136
+ gl.stencilFunc(gl.NOTEQUAL, this.maskLevel + 1, 1);
1137
+ }
1181
1138
  gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
1182
1139
  }
1183
1140
 
@@ -1185,13 +1142,16 @@ class WebGLRenderer extends Renderer {
1185
1142
  * disable (remove) the rendering mask set through setMask.
1186
1143
  * @name clearMask
1187
1144
  * @see WebGLRenderer#setMask
1188
- * @memberof WebGLRenderer.prototype
1145
+ * @memberof WebGLRenderer
1189
1146
  * @function
1190
1147
  */
1191
1148
  clearMask() {
1192
- // flush the compositor
1193
- this.flush();
1194
- this.gl.disable(this.gl.STENCIL_TEST);
1149
+ if (this.maskLevel > 0) {
1150
+ // flush the compositor
1151
+ this.flush();
1152
+ this.maskLevel = 0;
1153
+ this.gl.disable(this.gl.STENCIL_TEST);
1154
+ }
1195
1155
  }
1196
1156
  };
1197
1157