@vpmedia/phaser 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -3
- package/dist/phaser.cjs +1 -1
- package/dist/phaser.cjs.LICENSE.txt +1 -1
- package/dist/phaser.cjs.map +1 -1
- package/dist/phaser.js +1 -1
- package/dist/phaser.js.LICENSE.txt +1 -1
- package/dist/phaser.js.map +1 -1
- package/package.json +23 -17
- package/src/index.js +142 -0
- package/src/phaser/core/animation.js +355 -0
- package/src/phaser/core/animation_manager.js +238 -0
- package/src/phaser/core/animation_parser.js +133 -0
- package/src/phaser/core/array_set.js +107 -0
- package/src/phaser/core/cache.js +558 -0
- package/src/phaser/core/const.js +106 -0
- package/src/phaser/core/device.js +67 -0
- package/src/phaser/core/device_util.js +388 -0
- package/src/phaser/core/dom.js +207 -0
- package/src/phaser/core/event_manager.js +243 -0
- package/src/phaser/core/factory.js +74 -0
- package/src/phaser/core/frame.js +75 -0
- package/src/phaser/core/frame_data.js +84 -0
- package/src/phaser/core/frame_util.js +33 -0
- package/src/phaser/core/game.js +412 -0
- package/src/phaser/core/input.js +401 -0
- package/src/phaser/core/input_button.js +102 -0
- package/src/phaser/core/input_handler.js +687 -0
- package/src/phaser/core/input_mouse.js +289 -0
- package/src/phaser/core/input_mspointer.js +197 -0
- package/src/phaser/core/input_pointer.js +427 -0
- package/src/phaser/core/input_touch.js +157 -0
- package/src/phaser/core/loader.js +1057 -0
- package/src/phaser/core/loader_parser.js +109 -0
- package/src/phaser/core/raf.js +46 -0
- package/src/phaser/core/raf_fb.js +75 -0
- package/src/phaser/core/raf_to.js +34 -0
- package/src/phaser/core/scale_manager.js +806 -0
- package/src/phaser/core/scene.js +65 -0
- package/src/phaser/core/scene_manager.js +309 -0
- package/src/phaser/core/signal.js +175 -0
- package/src/phaser/core/signal_binding.js +69 -0
- package/src/phaser/core/sound.js +538 -0
- package/src/phaser/core/sound_manager.js +364 -0
- package/src/phaser/core/stage.js +108 -0
- package/src/phaser/core/time.js +203 -0
- package/src/phaser/core/timer.js +276 -0
- package/src/phaser/core/timer_event.js +21 -0
- package/src/phaser/core/tween.js +329 -0
- package/src/phaser/core/tween_data.js +258 -0
- package/src/phaser/core/tween_easing.js +341 -0
- package/src/phaser/core/tween_manager.js +185 -0
- package/src/phaser/core/world.js +18 -0
- package/src/phaser/display/bitmap_text.js +322 -0
- package/src/phaser/display/button.js +194 -0
- package/src/phaser/display/canvas/buffer.js +36 -0
- package/src/phaser/display/canvas/graphics.js +227 -0
- package/src/phaser/display/canvas/masker.js +39 -0
- package/src/phaser/display/canvas/pool.js +126 -0
- package/src/phaser/display/canvas/renderer.js +123 -0
- package/src/phaser/display/canvas/tinter.js +144 -0
- package/src/phaser/display/canvas/util.js +159 -0
- package/src/phaser/display/display_object.js +597 -0
- package/src/phaser/display/graphics.js +723 -0
- package/src/phaser/display/graphics_data.js +27 -0
- package/src/phaser/display/graphics_data_util.js +15 -0
- package/src/phaser/display/group.js +227 -0
- package/src/phaser/display/image.js +288 -0
- package/src/phaser/display/sprite_batch.js +15 -0
- package/src/phaser/display/sprite_util.js +250 -0
- package/src/phaser/display/text.js +1089 -0
- package/src/phaser/display/webgl/abstract_filter.js +25 -0
- package/src/phaser/display/webgl/base_texture.js +68 -0
- package/src/phaser/display/webgl/blend_manager.js +35 -0
- package/src/phaser/display/webgl/earcut.js +662 -0
- package/src/phaser/display/webgl/earcut_node.js +28 -0
- package/src/phaser/display/webgl/fast_sprite_batch.js +242 -0
- package/src/phaser/display/webgl/filter_manager.js +46 -0
- package/src/phaser/display/webgl/filter_texture.js +61 -0
- package/src/phaser/display/webgl/graphics.js +624 -0
- package/src/phaser/display/webgl/graphics_data.js +42 -0
- package/src/phaser/display/webgl/mask_manager.js +36 -0
- package/src/phaser/display/webgl/render_texture.js +81 -0
- package/src/phaser/display/webgl/renderer.js +234 -0
- package/src/phaser/display/webgl/shader/complex.js +74 -0
- package/src/phaser/display/webgl/shader/fast.js +97 -0
- package/src/phaser/display/webgl/shader/normal.js +225 -0
- package/src/phaser/display/webgl/shader/primitive.js +72 -0
- package/src/phaser/display/webgl/shader/strip.js +77 -0
- package/src/phaser/display/webgl/shader_manager.js +89 -0
- package/src/phaser/display/webgl/sprite_batch.js +320 -0
- package/src/phaser/display/webgl/stencil_manager.js +170 -0
- package/src/phaser/display/webgl/texture.js +117 -0
- package/src/phaser/display/webgl/texture_util.js +34 -0
- package/src/phaser/display/webgl/util.js +78 -0
- package/src/phaser/geom/circle.js +186 -0
- package/src/phaser/geom/ellipse.js +65 -0
- package/src/phaser/geom/line.js +190 -0
- package/src/phaser/geom/matrix.js +147 -0
- package/src/phaser/geom/point.js +164 -0
- package/src/phaser/geom/polygon.js +140 -0
- package/src/phaser/geom/rectangle.js +306 -0
- package/src/phaser/geom/rounded_rectangle.js +36 -0
- package/src/phaser/geom/util/circle.js +122 -0
- package/src/phaser/geom/util/ellipse.js +34 -0
- package/src/phaser/geom/util/line.js +135 -0
- package/src/phaser/geom/util/matrix.js +53 -0
- package/src/phaser/geom/util/point.js +296 -0
- package/src/phaser/geom/util/polygon.js +28 -0
- package/src/phaser/geom/util/rectangle.js +229 -0
- package/src/phaser/geom/util/rounded_rectangle.js +32 -0
- package/src/phaser/util/math.js +297 -0
- package/src/phaser/util/string.js +32 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Andras Csizmadia <andras@vpmedia.hu>
|
|
3
|
+
* @author Richard Davey <rich@photonstorm.com>
|
|
4
|
+
* @author Mat Groves http://matgroves.com/ @Doormat23
|
|
5
|
+
* @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
|
|
6
|
+
*/
|
|
7
|
+
import { create, removeByCanvas } from './pool';
|
|
8
|
+
|
|
9
|
+
export default class {
|
|
10
|
+
|
|
11
|
+
constructor(width, height) {
|
|
12
|
+
this.width = width;
|
|
13
|
+
this.height = height;
|
|
14
|
+
this.canvas = create(this, this.width, this.height);
|
|
15
|
+
this.context = this.canvas.getContext('2d');
|
|
16
|
+
this.canvas.width = width;
|
|
17
|
+
this.canvas.height = height;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
clear() {
|
|
21
|
+
this.context.setTransform(1, 0, 0, 1, 0, 0);
|
|
22
|
+
this.context.clearRect(0, 0, this.width, this.height);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
resize(width, height) {
|
|
26
|
+
this.width = width;
|
|
27
|
+
this.height = height;
|
|
28
|
+
this.canvas.width = width;
|
|
29
|
+
this.canvas.height = height;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
destroy() {
|
|
33
|
+
removeByCanvas(this.canvas);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Andras Csizmadia <andras@vpmedia.hu>
|
|
3
|
+
* @author Richard Davey <rich@photonstorm.com>
|
|
4
|
+
* @author Mat Groves http://matgroves.com/ @Doormat23
|
|
5
|
+
* @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
|
|
6
|
+
*/
|
|
7
|
+
import { GEOM_POLYGON, GEOM_RECTANGLE, GEOM_CIRCLE, GEOM_ELLIPSE, GEOM_ROUNDED_RECTANGLE } from '../../core/const';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param {object} graphics TBD
|
|
12
|
+
*/
|
|
13
|
+
export function updateGraphicsTint(graphics) {
|
|
14
|
+
if (graphics.tint === 0xFFFFFF) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const tintR = (graphics.tint >> 16 & 0xFF) / 255;
|
|
18
|
+
const tintG = (graphics.tint >> 8 & 0xFF) / 255;
|
|
19
|
+
const tintB = (graphics.tint & 0xFF) / 255;
|
|
20
|
+
for (let i = 0; i < graphics.graphicsData.length; i += 1) {
|
|
21
|
+
const data = graphics.graphicsData[i];
|
|
22
|
+
const fillColor = data.fillColor | 0;
|
|
23
|
+
const lineColor = data.lineColor | 0;
|
|
24
|
+
data._fillTint = (((fillColor >> 16 & 0xFF) / 255 * tintR * 255 << 16) + ((fillColor >> 8 & 0xFF) / 255 * tintG * 255 << 8) + (fillColor & 0xFF) / 255 * tintB * 255);
|
|
25
|
+
data._lineTint = (((lineColor >> 16 & 0xFF) / 255 * tintR * 255 << 16) + ((lineColor >> 8 & 0xFF) / 255 * tintG * 255 << 8) + (lineColor & 0xFF) / 255 * tintB * 255);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @param {object} graphics TBD
|
|
32
|
+
* @param {object} context TBD
|
|
33
|
+
*/
|
|
34
|
+
export function renderGraphics(graphics, context) {
|
|
35
|
+
const worldAlpha = graphics.worldAlpha;
|
|
36
|
+
if (graphics.dirty) {
|
|
37
|
+
updateGraphicsTint(graphics);
|
|
38
|
+
graphics.dirty = false;
|
|
39
|
+
}
|
|
40
|
+
for (let i = 0; i < graphics.graphicsData.length; i += 1) {
|
|
41
|
+
const data = graphics.graphicsData[i];
|
|
42
|
+
const shape = data.shape;
|
|
43
|
+
const fillColor = data._fillTint;
|
|
44
|
+
const lineColor = data._lineTint;
|
|
45
|
+
context.lineWidth = data.lineWidth;
|
|
46
|
+
if (data.type === GEOM_POLYGON) {
|
|
47
|
+
context.beginPath();
|
|
48
|
+
const points = shape.points;
|
|
49
|
+
context.moveTo(points[0], points[1]);
|
|
50
|
+
for (let j = 1; j < points.length / 2; j += 1) {
|
|
51
|
+
context.lineTo(points[j * 2], points[j * 2 + 1]);
|
|
52
|
+
}
|
|
53
|
+
if (shape.closed) {
|
|
54
|
+
context.lineTo(points[0], points[1]);
|
|
55
|
+
}
|
|
56
|
+
// if the first and last point are the same close the path - much neater :)
|
|
57
|
+
if (points[0] === points[points.length - 2] && points[1] === points[points.length - 1]) {
|
|
58
|
+
context.closePath();
|
|
59
|
+
}
|
|
60
|
+
if (data.fill) {
|
|
61
|
+
context.globalAlpha = data.fillAlpha * worldAlpha;
|
|
62
|
+
context.fillStyle = '#' + ('00000' + (fillColor | 0).toString(16)).substr(-6);
|
|
63
|
+
context.fill();
|
|
64
|
+
}
|
|
65
|
+
if (data.lineWidth) {
|
|
66
|
+
context.globalAlpha = data.lineAlpha * worldAlpha;
|
|
67
|
+
context.strokeStyle = '#' + ('00000' + (lineColor | 0).toString(16)).substr(-6);
|
|
68
|
+
context.stroke();
|
|
69
|
+
}
|
|
70
|
+
} else if (data.type === GEOM_RECTANGLE) {
|
|
71
|
+
if (data.fillColor || data.fillColor === 0) {
|
|
72
|
+
context.globalAlpha = data.fillAlpha * worldAlpha;
|
|
73
|
+
context.fillStyle = '#' + ('00000' + (fillColor | 0).toString(16)).substr(-6);
|
|
74
|
+
context.fillRect(shape.x, shape.y, shape.width, shape.height);
|
|
75
|
+
}
|
|
76
|
+
if (data.lineWidth) {
|
|
77
|
+
context.globalAlpha = data.lineAlpha * worldAlpha;
|
|
78
|
+
context.strokeStyle = '#' + ('00000' + (lineColor | 0).toString(16)).substr(-6);
|
|
79
|
+
context.strokeRect(shape.x, shape.y, shape.width, shape.height);
|
|
80
|
+
}
|
|
81
|
+
} else if (data.type === GEOM_CIRCLE) {
|
|
82
|
+
context.beginPath();
|
|
83
|
+
context.arc(shape.x, shape.y, shape.radius, 0, 2 * Math.PI);
|
|
84
|
+
context.closePath();
|
|
85
|
+
if (data.fill) {
|
|
86
|
+
context.globalAlpha = data.fillAlpha * worldAlpha;
|
|
87
|
+
context.fillStyle = '#' + ('00000' + (fillColor | 0).toString(16)).substr(-6);
|
|
88
|
+
context.fill();
|
|
89
|
+
}
|
|
90
|
+
if (data.lineWidth) {
|
|
91
|
+
context.globalAlpha = data.lineAlpha * worldAlpha;
|
|
92
|
+
context.strokeStyle = '#' + ('00000' + (lineColor | 0).toString(16)).substr(-6);
|
|
93
|
+
context.stroke();
|
|
94
|
+
}
|
|
95
|
+
} else if (data.type === GEOM_ELLIPSE) {
|
|
96
|
+
// ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
|
|
97
|
+
const w = shape.width * 2;
|
|
98
|
+
const h = shape.height * 2;
|
|
99
|
+
const x = shape.x - w / 2;
|
|
100
|
+
const y = shape.y - h / 2;
|
|
101
|
+
context.beginPath();
|
|
102
|
+
const kappa = 0.5522848;
|
|
103
|
+
const ox = (w / 2) * kappa; // control point offset horizontal
|
|
104
|
+
const oy = (h / 2) * kappa; // control point offset vertical
|
|
105
|
+
const xe = x + w; // x-end
|
|
106
|
+
const ye = y + h; // y-end
|
|
107
|
+
const xm = x + w / 2; // x-middle
|
|
108
|
+
const ym = y + h / 2; // y-middle
|
|
109
|
+
context.moveTo(x, ym);
|
|
110
|
+
context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
|
|
111
|
+
context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
|
|
112
|
+
context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
|
|
113
|
+
context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
|
|
114
|
+
context.closePath();
|
|
115
|
+
if (data.fill) {
|
|
116
|
+
context.globalAlpha = data.fillAlpha * worldAlpha;
|
|
117
|
+
context.fillStyle = '#' + ('00000' + (fillColor | 0).toString(16)).substr(-6);
|
|
118
|
+
context.fill();
|
|
119
|
+
}
|
|
120
|
+
if (data.lineWidth) {
|
|
121
|
+
context.globalAlpha = data.lineAlpha * worldAlpha;
|
|
122
|
+
context.strokeStyle = '#' + ('00000' + (lineColor | 0).toString(16)).substr(-6);
|
|
123
|
+
context.stroke();
|
|
124
|
+
}
|
|
125
|
+
} else if (data.type === GEOM_ROUNDED_RECTANGLE) {
|
|
126
|
+
const rx = shape.x;
|
|
127
|
+
const ry = shape.y;
|
|
128
|
+
const width = shape.width;
|
|
129
|
+
const height = shape.height;
|
|
130
|
+
let radius = shape.radius;
|
|
131
|
+
const maxRadius = Math.min(width, height) / 2 | 0;
|
|
132
|
+
radius = radius > maxRadius ? maxRadius : radius;
|
|
133
|
+
context.beginPath();
|
|
134
|
+
context.moveTo(rx, ry + radius);
|
|
135
|
+
context.lineTo(rx, ry + height - radius);
|
|
136
|
+
context.quadraticCurveTo(rx, ry + height, rx + radius, ry + height);
|
|
137
|
+
context.lineTo(rx + width - radius, ry + height);
|
|
138
|
+
context.quadraticCurveTo(rx + width, ry + height, rx + width, ry + height - radius);
|
|
139
|
+
context.lineTo(rx + width, ry + radius);
|
|
140
|
+
context.quadraticCurveTo(rx + width, ry, rx + width - radius, ry);
|
|
141
|
+
context.lineTo(rx + radius, ry);
|
|
142
|
+
context.quadraticCurveTo(rx, ry, rx, ry + radius);
|
|
143
|
+
context.closePath();
|
|
144
|
+
if (data.fillColor || data.fillColor === 0) {
|
|
145
|
+
context.globalAlpha = data.fillAlpha * worldAlpha;
|
|
146
|
+
context.fillStyle = '#' + ('00000' + (fillColor | 0).toString(16)).substr(-6);
|
|
147
|
+
context.fill();
|
|
148
|
+
}
|
|
149
|
+
if (data.lineWidth) {
|
|
150
|
+
context.globalAlpha = data.lineAlpha * worldAlpha;
|
|
151
|
+
context.strokeStyle = '#' + ('00000' + (lineColor | 0).toString(16)).substr(-6);
|
|
152
|
+
context.stroke();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
*
|
|
160
|
+
* @param {object} graphics TBD
|
|
161
|
+
* @param {object} context TBD
|
|
162
|
+
*/
|
|
163
|
+
export function renderGraphicsMask(graphics, context) {
|
|
164
|
+
const len = graphics.graphicsData.length;
|
|
165
|
+
if (len === 0) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
context.beginPath();
|
|
169
|
+
for (let i = 0; i < len; i += 1) {
|
|
170
|
+
const data = graphics.graphicsData[i];
|
|
171
|
+
const shape = data.shape;
|
|
172
|
+
if (data.type === GEOM_POLYGON) {
|
|
173
|
+
const points = shape.points;
|
|
174
|
+
context.moveTo(points[0], points[1]);
|
|
175
|
+
for (let j = 1; j < points.length / 2; j += 1) {
|
|
176
|
+
context.lineTo(points[j * 2], points[j * 2 + 1]);
|
|
177
|
+
}
|
|
178
|
+
// if the first and last point are the same close the path - much neater :)
|
|
179
|
+
if (points[0] === points[points.length - 2] && points[1] === points[points.length - 1]) {
|
|
180
|
+
context.closePath();
|
|
181
|
+
}
|
|
182
|
+
} else if (data.type === GEOM_RECTANGLE) {
|
|
183
|
+
context.rect(shape.x, shape.y, shape.width, shape.height);
|
|
184
|
+
context.closePath();
|
|
185
|
+
} else if (data.type === GEOM_CIRCLE) {
|
|
186
|
+
context.arc(shape.x, shape.y, shape.radius, 0, 2 * Math.PI);
|
|
187
|
+
context.closePath();
|
|
188
|
+
} else if (data.type === GEOM_ELLIPSE) {
|
|
189
|
+
// ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
|
|
190
|
+
const w = shape.width * 2;
|
|
191
|
+
const h = shape.height * 2;
|
|
192
|
+
const x = shape.x - w / 2;
|
|
193
|
+
const y = shape.y - h / 2;
|
|
194
|
+
const kappa = 0.5522848;
|
|
195
|
+
const ox = (w / 2) * kappa; // control point offset horizontal
|
|
196
|
+
const oy = (h / 2) * kappa; // control point offset vertical
|
|
197
|
+
const xe = x + w; // x-end
|
|
198
|
+
const ye = y + h; // y-end
|
|
199
|
+
const xm = x + w / 2; // x-middle
|
|
200
|
+
const ym = y + h / 2; // y-middle
|
|
201
|
+
context.moveTo(x, ym);
|
|
202
|
+
context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
|
|
203
|
+
context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
|
|
204
|
+
context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
|
|
205
|
+
context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
|
|
206
|
+
context.closePath();
|
|
207
|
+
} else if (data.type === GEOM_ROUNDED_RECTANGLE) {
|
|
208
|
+
const rx = shape.x;
|
|
209
|
+
const ry = shape.y;
|
|
210
|
+
const width = shape.width;
|
|
211
|
+
const height = shape.height;
|
|
212
|
+
let radius = shape.radius;
|
|
213
|
+
const maxRadius = Math.min(width, height) / 2 | 0;
|
|
214
|
+
radius = radius > maxRadius ? maxRadius : radius;
|
|
215
|
+
context.moveTo(rx, ry + radius);
|
|
216
|
+
context.lineTo(rx, ry + height - radius);
|
|
217
|
+
context.quadraticCurveTo(rx, ry + height, rx + radius, ry + height);
|
|
218
|
+
context.lineTo(rx + width - radius, ry + height);
|
|
219
|
+
context.quadraticCurveTo(rx + width, ry + height, rx + width, ry + height - radius);
|
|
220
|
+
context.lineTo(rx + width, ry + radius);
|
|
221
|
+
context.quadraticCurveTo(rx + width, ry, rx + width - radius, ry);
|
|
222
|
+
context.lineTo(rx + radius, ry);
|
|
223
|
+
context.quadraticCurveTo(rx, ry, rx, ry + radius);
|
|
224
|
+
context.closePath();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Andras Csizmadia <andras@vpmedia.hu>
|
|
3
|
+
* @author Richard Davey <rich@photonstorm.com>
|
|
4
|
+
* @author Mat Groves http://matgroves.com/ @Doormat23
|
|
5
|
+
* @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
|
|
6
|
+
*/
|
|
7
|
+
import { renderGraphicsMask } from './graphics';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param {object} maskData TBD
|
|
12
|
+
* @param {object} renderSession TBD
|
|
13
|
+
*/
|
|
14
|
+
export function pushMask(maskData, renderSession) {
|
|
15
|
+
const context = renderSession.context;
|
|
16
|
+
context.save();
|
|
17
|
+
const cacheAlpha = maskData.alpha;
|
|
18
|
+
const transform = maskData.worldTransform;
|
|
19
|
+
const resolution = renderSession.resolution;
|
|
20
|
+
context.setTransform(
|
|
21
|
+
transform.a * resolution,
|
|
22
|
+
transform.b * resolution,
|
|
23
|
+
transform.c * resolution,
|
|
24
|
+
transform.d * resolution,
|
|
25
|
+
transform.tx * resolution,
|
|
26
|
+
transform.ty * resolution,
|
|
27
|
+
);
|
|
28
|
+
renderGraphicsMask(maskData, context);
|
|
29
|
+
context.clip();
|
|
30
|
+
maskData.worldAlpha = cacheAlpha;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @param {object} renderSession TBD
|
|
36
|
+
*/
|
|
37
|
+
export function popMask(renderSession) {
|
|
38
|
+
renderSession.context.restore();
|
|
39
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Andras Csizmadia <andras@vpmedia.hu>
|
|
3
|
+
* @author Richard Davey <rich@photonstorm.com>
|
|
4
|
+
* @author Mat Groves http://matgroves.com/ @Doormat23
|
|
5
|
+
* @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @returns {object} TBD
|
|
11
|
+
*/
|
|
12
|
+
export function getPool() {
|
|
13
|
+
if (!window.PhaserRegistry) {
|
|
14
|
+
window.PhaserRegistry = {};
|
|
15
|
+
}
|
|
16
|
+
if (!window.PhaserRegistry.CANVAS_POOL) {
|
|
17
|
+
window.PhaserRegistry.CANVAS_POOL = [];
|
|
18
|
+
}
|
|
19
|
+
return window.PhaserRegistry.CANVAS_POOL;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @returns {object} TBD
|
|
25
|
+
*/
|
|
26
|
+
export function getFirst() {
|
|
27
|
+
const pool = getPool();
|
|
28
|
+
for (let i = 0; i < pool.length; i += 1) {
|
|
29
|
+
if (!pool[i].parent) {
|
|
30
|
+
return i;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return -1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @param {object} parent TBD
|
|
39
|
+
*/
|
|
40
|
+
export function remove(parent) {
|
|
41
|
+
const pool = getPool();
|
|
42
|
+
for (let i = 0; i < pool.length; i += 1) {
|
|
43
|
+
if (pool[i].parent === parent) {
|
|
44
|
+
pool[i].parent = null;
|
|
45
|
+
pool[i].canvas.width = 1;
|
|
46
|
+
pool[i].canvas.height = 1;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @param {object} canvas TBD
|
|
54
|
+
*/
|
|
55
|
+
export function removeByCanvas(canvas) {
|
|
56
|
+
const pool = getPool();
|
|
57
|
+
for (let i = 0; i < pool.length; i += 1) {
|
|
58
|
+
if (pool[i].canvas === canvas) {
|
|
59
|
+
pool[i].parent = null;
|
|
60
|
+
pool[i].canvas.width = 1;
|
|
61
|
+
pool[i].canvas.height = 1;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
*
|
|
68
|
+
* @returns {number} TBD
|
|
69
|
+
*/
|
|
70
|
+
export function getTotal() {
|
|
71
|
+
const pool = getPool();
|
|
72
|
+
let c = 0;
|
|
73
|
+
for (let i = 0; i < pool.length; i += 1) {
|
|
74
|
+
if (pool[i].parent) {
|
|
75
|
+
c += 1;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return c;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
*
|
|
83
|
+
* @returns {number} TBD
|
|
84
|
+
*/
|
|
85
|
+
export function getFree() {
|
|
86
|
+
const pool = getPool();
|
|
87
|
+
let c = 0;
|
|
88
|
+
for (let i = 0; i < pool.length; i += 1) {
|
|
89
|
+
if (!pool[i].parent) {
|
|
90
|
+
c += 1;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return c;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
*
|
|
98
|
+
* @param {object} parent TBD
|
|
99
|
+
* @param {number} width TBD
|
|
100
|
+
* @param {number} height TBD
|
|
101
|
+
* @returns {object} TBD
|
|
102
|
+
*/
|
|
103
|
+
export function create(parent, width, height) {
|
|
104
|
+
if (parent === undefined) {
|
|
105
|
+
console.warn('Created CanvasPool element with undefined parent.');
|
|
106
|
+
}
|
|
107
|
+
const idx = getFirst();
|
|
108
|
+
const pool = getPool();
|
|
109
|
+
let canvas;
|
|
110
|
+
if (idx === -1) {
|
|
111
|
+
const container = {
|
|
112
|
+
parent,
|
|
113
|
+
canvas: document.createElement('canvas'),
|
|
114
|
+
};
|
|
115
|
+
pool.push(container);
|
|
116
|
+
canvas = container.canvas;
|
|
117
|
+
} else {
|
|
118
|
+
pool[idx].parent = parent;
|
|
119
|
+
canvas = pool[idx].canvas;
|
|
120
|
+
}
|
|
121
|
+
if (width !== undefined) {
|
|
122
|
+
canvas.width = width;
|
|
123
|
+
canvas.height = height;
|
|
124
|
+
}
|
|
125
|
+
return canvas;
|
|
126
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Andras Csizmadia <andras@vpmedia.hu>
|
|
3
|
+
* @author Richard Davey <rich@photonstorm.com>
|
|
4
|
+
* @author Mat Groves http://matgroves.com/ @Doormat23
|
|
5
|
+
* @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
|
|
6
|
+
*/
|
|
7
|
+
import { RENDER_CANVAS, SCALE_LINEAR, BLEND_NORMAL, BLEND_ADD, BLEND_MULTIPLY, BLEND_SCREEN, BLEND_OVERLAY, BLEND_DARKEN, BLEND_LIGHTEN, BLEND_COLOR_DODGE, BLEND_COLOR_BURN, BLEND_HARD_LIGHT, BLEND_SOFT_LIGHT, BLEND_DIFFERENCE, BLEND_EXCLUSION, BLEND_HUE, BLEND_SATURATION, BLEND_COLOR, BLEND_LUMINOSITY } from '../../core/const';
|
|
8
|
+
import { getSmoothingPrefix } from './util';
|
|
9
|
+
import { detectCapabilities } from './tinter';
|
|
10
|
+
import * as CanvasMaskManager from './masker';
|
|
11
|
+
|
|
12
|
+
export default class {
|
|
13
|
+
|
|
14
|
+
constructor(game) {
|
|
15
|
+
detectCapabilities();
|
|
16
|
+
this.type = RENDER_CANVAS;
|
|
17
|
+
this.resolution = game.config.resolution;
|
|
18
|
+
this.clearBeforeRender = game.config.clearBeforeRender;
|
|
19
|
+
this.transparent = game.config.transparent;
|
|
20
|
+
this.autoResize = false;
|
|
21
|
+
this.width = game.width * this.resolution;
|
|
22
|
+
this.height = game.height * this.resolution;
|
|
23
|
+
this.view = game.canvas;
|
|
24
|
+
this.context = this.view.getContext('2d', { alpha: this.transparent });
|
|
25
|
+
if (!this.context) {
|
|
26
|
+
throw new Error('Error creating Canvas 2D context.');
|
|
27
|
+
}
|
|
28
|
+
this.refresh = true;
|
|
29
|
+
this.count = 0;
|
|
30
|
+
this.renderSession = {
|
|
31
|
+
context: this.context,
|
|
32
|
+
maskManager: CanvasMaskManager,
|
|
33
|
+
scaleMode: null,
|
|
34
|
+
smoothProperty: getSmoothingPrefix(this.context),
|
|
35
|
+
roundPixels: false,
|
|
36
|
+
};
|
|
37
|
+
this.mapBlendModes();
|
|
38
|
+
this.resize(this.width, this.height);
|
|
39
|
+
window.PhaserRegistry.DEFAULT_RENDERER = this;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
render(root) {
|
|
43
|
+
if (!this.context) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.context.setTransform(1, 0, 0, 1, 0, 0);
|
|
47
|
+
this.context.globalAlpha = 1;
|
|
48
|
+
this.renderSession.currentBlendMode = 0;
|
|
49
|
+
this.renderSession.shakeX = 0;
|
|
50
|
+
this.renderSession.shakeY = 0;
|
|
51
|
+
this.context.globalCompositeOperation = 'source-over';
|
|
52
|
+
if (navigator.isCocoonJS && this.view.screencanvas) {
|
|
53
|
+
this.context.fillStyle = 'black';
|
|
54
|
+
this.context.clear();
|
|
55
|
+
}
|
|
56
|
+
if (this.clearBeforeRender) {
|
|
57
|
+
if (this.transparent) {
|
|
58
|
+
this.context.clearRect(0, 0, this.width, this.height);
|
|
59
|
+
} else if (root._bgColor) {
|
|
60
|
+
this.context.fillStyle = root._bgColor.rgba;
|
|
61
|
+
this.context.fillRect(0, 0, this.width, this.height);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
this.renderDisplayObject(root);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
destroy(removeView = true) {
|
|
68
|
+
if (removeView && this.view.parent) {
|
|
69
|
+
this.view.parent.removeChild(this.view);
|
|
70
|
+
}
|
|
71
|
+
this.view = null;
|
|
72
|
+
this.context = null;
|
|
73
|
+
this.renderSession = null;
|
|
74
|
+
window.PhaserRegistry.DEFAULT_RENDERER = null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
resize(width, height) {
|
|
78
|
+
this.width = width * this.resolution;
|
|
79
|
+
this.height = height * this.resolution;
|
|
80
|
+
this.view.width = this.width;
|
|
81
|
+
this.view.height = this.height;
|
|
82
|
+
if (this.autoResize) {
|
|
83
|
+
this.view.style.width = this.width / this.resolution + 'px';
|
|
84
|
+
this.view.style.height = this.height / this.resolution + 'px';
|
|
85
|
+
}
|
|
86
|
+
if (this.renderSession.smoothProperty) {
|
|
87
|
+
this.context[this.renderSession.smoothProperty] = (this.renderSession.scaleMode === SCALE_LINEAR);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
renderDisplayObject(displayObject, context, matrix) {
|
|
92
|
+
this.renderSession.context = context || this.context;
|
|
93
|
+
this.renderSession.resolution = this.resolution;
|
|
94
|
+
displayObject.renderCanvas(this.renderSession, matrix);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
mapBlendModes() {
|
|
98
|
+
if (window.PhaserRegistry.blendModesCanvas) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const b = [];
|
|
102
|
+
const useNew = window.PhaserRegistry.CAN_CANVAS_USE_MULTIPLY;
|
|
103
|
+
b[BLEND_NORMAL] = 'source-over';
|
|
104
|
+
b[BLEND_ADD] = 'lighter';
|
|
105
|
+
b[BLEND_MULTIPLY] = (useNew) ? 'multiply' : 'source-over';
|
|
106
|
+
b[BLEND_SCREEN] = (useNew) ? 'screen' : 'source-over';
|
|
107
|
+
b[BLEND_OVERLAY] = (useNew) ? 'overlay' : 'source-over';
|
|
108
|
+
b[BLEND_DARKEN] = (useNew) ? 'darken' : 'source-over';
|
|
109
|
+
b[BLEND_LIGHTEN] = (useNew) ? 'lighten' : 'source-over';
|
|
110
|
+
b[BLEND_COLOR_DODGE] = (useNew) ? 'color-dodge' : 'source-over';
|
|
111
|
+
b[BLEND_COLOR_BURN] = (useNew) ? 'color-burn' : 'source-over';
|
|
112
|
+
b[BLEND_HARD_LIGHT] = (useNew) ? 'hard-light' : 'source-over';
|
|
113
|
+
b[BLEND_SOFT_LIGHT] = (useNew) ? 'soft-light' : 'source-over';
|
|
114
|
+
b[BLEND_DIFFERENCE] = (useNew) ? 'difference' : 'source-over';
|
|
115
|
+
b[BLEND_EXCLUSION] = (useNew) ? 'exclusion' : 'source-over';
|
|
116
|
+
b[BLEND_HUE] = (useNew) ? 'hue' : 'source-over';
|
|
117
|
+
b[BLEND_SATURATION] = (useNew) ? 'saturation' : 'source-over';
|
|
118
|
+
b[BLEND_COLOR] = (useNew) ? 'color' : 'source-over';
|
|
119
|
+
b[BLEND_LUMINOSITY] = (useNew) ? 'luminosity' : 'source-over';
|
|
120
|
+
window.PhaserRegistry.blendModesCanvas = b;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Andras Csizmadia <andras@vpmedia.hu>
|
|
3
|
+
* @author Richard Davey <rich@photonstorm.com>
|
|
4
|
+
* @author Mat Groves http://matgroves.com/ @Doormat23
|
|
5
|
+
* @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
|
|
6
|
+
*/
|
|
7
|
+
import CanvasBuffer from './buffer';
|
|
8
|
+
import { create, removeByCanvas } from './pool';
|
|
9
|
+
import { hex2rgb } from '../../util/math';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param {object} sprite TBD
|
|
14
|
+
* @param {object} color TBD
|
|
15
|
+
* @returns {object} TBD
|
|
16
|
+
*/
|
|
17
|
+
export function getTintedTexture(sprite, color) {
|
|
18
|
+
const canvas = sprite.tintedTexture || create('CanvasTinter');
|
|
19
|
+
window.PhaserRegistry.CANVAS_TINT_METHOD(sprite.texture, color, canvas);
|
|
20
|
+
return canvas;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param {object} texture TBD
|
|
26
|
+
* @param {object} color TBD
|
|
27
|
+
* @param {object} canvas TBD
|
|
28
|
+
*/
|
|
29
|
+
export function tintWithMultiply(texture, color, canvas) {
|
|
30
|
+
const context = canvas.getContext('2d');
|
|
31
|
+
const crop = texture.crop;
|
|
32
|
+
if (canvas.width !== crop.width || canvas.height !== crop.height) {
|
|
33
|
+
canvas.width = crop.width;
|
|
34
|
+
canvas.height = crop.height;
|
|
35
|
+
}
|
|
36
|
+
context.clearRect(0, 0, crop.width, crop.height);
|
|
37
|
+
context.fillStyle = '#' + ('00000' + (color | 0).toString(16)).substr(-6);
|
|
38
|
+
context.fillRect(0, 0, crop.width, crop.height);
|
|
39
|
+
context.globalCompositeOperation = 'multiply';
|
|
40
|
+
context.drawImage(texture.baseTexture.source, crop.x, crop.y, crop.width, crop.height, 0, 0, crop.width, crop.height);
|
|
41
|
+
context.globalCompositeOperation = 'destination-atop';
|
|
42
|
+
context.drawImage(texture.baseTexture.source, crop.x, crop.y, crop.width, crop.height, 0, 0, crop.width, crop.height);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @param {object} texture TBD
|
|
48
|
+
* @param {object} color TBD
|
|
49
|
+
* @param {object} canvas TBD
|
|
50
|
+
*/
|
|
51
|
+
export function tintWithPerPixel(texture, color, canvas) {
|
|
52
|
+
const context = canvas.getContext('2d');
|
|
53
|
+
const crop = texture.crop;
|
|
54
|
+
canvas.width = crop.width;
|
|
55
|
+
canvas.height = crop.height;
|
|
56
|
+
context.globalCompositeOperation = 'copy';
|
|
57
|
+
context.drawImage(texture.baseTexture.source, crop.x, crop.y, crop.width, crop.height, 0, 0, crop.width, crop.height);
|
|
58
|
+
const rgbValues = hex2rgb(color);
|
|
59
|
+
const r = rgbValues[0];
|
|
60
|
+
const g = rgbValues[1];
|
|
61
|
+
const b = rgbValues[2];
|
|
62
|
+
const pixelData = context.getImageData(0, 0, crop.width, crop.height);
|
|
63
|
+
const pixels = pixelData.data;
|
|
64
|
+
for (let i = 0; i < pixels.length; i += 4) {
|
|
65
|
+
pixels[i + 0] *= r;
|
|
66
|
+
pixels[i + 1] *= g;
|
|
67
|
+
pixels[i + 2] *= b;
|
|
68
|
+
const canHandleAlpha = window.PhaserRegistry.CAN_CANVAS_HANDLE_ALPHA;
|
|
69
|
+
if (!canHandleAlpha) {
|
|
70
|
+
const alpha = pixels[i + 3];
|
|
71
|
+
pixels[i + 0] /= 255 / alpha;
|
|
72
|
+
pixels[i + 1] /= 255 / alpha;
|
|
73
|
+
pixels[i + 2] /= 255 / alpha;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
context.putImageData(pixelData, 0, 0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @returns {boolean} TBD
|
|
82
|
+
*/
|
|
83
|
+
export function checkInverseAlpha() {
|
|
84
|
+
const canvas = new CanvasBuffer(2, 1);
|
|
85
|
+
canvas.context.fillStyle = 'rgba(10, 20, 30, 0.5)';
|
|
86
|
+
// Draw a single pixel
|
|
87
|
+
canvas.context.fillRect(0, 0, 1, 1);
|
|
88
|
+
// Get the color values
|
|
89
|
+
const s1 = canvas.context.getImageData(0, 0, 1, 1);
|
|
90
|
+
if (s1 === null) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
// Plot them to x2
|
|
94
|
+
canvas.context.putImageData(s1, 1, 0);
|
|
95
|
+
// Get those values
|
|
96
|
+
const s2 = canvas.context.getImageData(1, 0, 1, 1);
|
|
97
|
+
// Compare and return
|
|
98
|
+
return (s2.data[0] === s1.data[0] && s2.data[1] === s1.data[1] && s2.data[2] === s1.data[2] && s2.data[3] === s1.data[3]);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
*
|
|
103
|
+
* @returns {boolean} TBD
|
|
104
|
+
*/
|
|
105
|
+
export function canUseNewCanvasBlendModes() {
|
|
106
|
+
if (document === undefined) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
const pngHead = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAABAQMAAADD8p2OAAAAA1BMVEX/';
|
|
110
|
+
const pngEnd = 'AAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==';
|
|
111
|
+
const magenta = new Image();
|
|
112
|
+
magenta.src = pngHead + 'AP804Oa6' + pngEnd;
|
|
113
|
+
const yellow = new Image();
|
|
114
|
+
yellow.src = pngHead + '/wCKxvRF' + pngEnd;
|
|
115
|
+
const canvas = create('CanvasTinter', 6, 1);
|
|
116
|
+
const context = canvas.getContext('2d');
|
|
117
|
+
context.globalCompositeOperation = 'multiply';
|
|
118
|
+
context.drawImage(magenta, 0, 0);
|
|
119
|
+
context.drawImage(yellow, 2, 0);
|
|
120
|
+
if (!context.getImageData(2, 0, 1, 1)) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
const data = context.getImageData(2, 0, 1, 1).data;
|
|
124
|
+
removeByCanvas(canvas);
|
|
125
|
+
return (data[0] === 255 && data[1] === 0 && data[2] === 0);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* TBD
|
|
130
|
+
*/
|
|
131
|
+
export function detectCapabilities() {
|
|
132
|
+
if (!window.PhaserRegistry) {
|
|
133
|
+
window.PhaserRegistry = {};
|
|
134
|
+
}
|
|
135
|
+
if (!window.PhaserRegistry.CAN_CANVAS_HANDLE_ALPHA) {
|
|
136
|
+
window.PhaserRegistry.CAN_CANVAS_HANDLE_ALPHA = checkInverseAlpha();
|
|
137
|
+
}
|
|
138
|
+
if (!window.PhaserRegistry.CAN_CANVAS_USE_MULTIPLY) {
|
|
139
|
+
window.PhaserRegistry.CAN_CANVAS_USE_MULTIPLY = canUseNewCanvasBlendModes();
|
|
140
|
+
}
|
|
141
|
+
if (!window.PhaserRegistry.CANVAS_TINT_METHOD) {
|
|
142
|
+
window.PhaserRegistry.CANVAS_TINT_METHOD = window.PhaserRegistry.CAN_CANVAS_USE_MULTIPLY ? tintWithMultiply : tintWithPerPixel;
|
|
143
|
+
}
|
|
144
|
+
}
|