@vpmedia/phaser 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/phaser.cjs.LICENSE.txt +1 -1
- package/dist/phaser.js.LICENSE.txt +1 -1
- package/package.json +2 -3
- package/src/index.js +99 -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 +130 -0
- package/src/phaser/core/array_set.js +108 -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 +386 -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 +31 -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 +946 -0
- package/src/phaser/core/loader_parser.js +105 -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 +66 -0
- package/src/phaser/core/scene_manager.js +310 -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 +365 -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 +316 -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 +121 -0
- package/src/phaser/display/canvas/renderer.js +123 -0
- package/src/phaser/display/canvas/tinter.js +141 -0
- package/src/phaser/display/canvas/util.js +151 -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 +14 -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 +248 -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 +647 -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 +618 -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 +32 -0
- package/src/phaser/display/webgl/util.js +74 -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 +141 -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 +115 -0
- package/src/phaser/geom/util/ellipse.js +30 -0
- package/src/phaser/geom/util/line.js +130 -0
- package/src/phaser/geom/util/matrix.js +48 -0
- package/src/phaser/geom/util/point.js +276 -0
- package/src/phaser/geom/util/polygon.js +24 -0
- package/src/phaser/geom/util/rectangle.js +212 -0
- package/src/phaser/geom/util/rounded_rectangle.js +28 -0
- package/src/phaser/util/math.js +279 -0
- package/src/phaser/util/string.js +26 -0
|
@@ -0,0 +1,618 @@
|
|
|
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 GraphicsData from './graphics_data';
|
|
8
|
+
import Point from '../../geom/point';
|
|
9
|
+
import { GEOM_CIRCLE, GEOM_ELLIPSE, GEOM_POLYGON, GEOM_RECTANGLE, GEOM_ROUNDED_RECTANGLE } from '../../core/const';
|
|
10
|
+
import { hex2rgb } from '../../util/math';
|
|
11
|
+
import { triangulate } from './earcut';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
export function getStencilBufferLimit() {
|
|
17
|
+
if (!window.PhaserRegistry.stencilBufferLimit) {
|
|
18
|
+
window.PhaserRegistry.stencilBufferLimit = 6;
|
|
19
|
+
}
|
|
20
|
+
return window.PhaserRegistry.stencilBufferLimit;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
export function getGraphicsDataPool() {
|
|
27
|
+
if (!window.PhaserRegistry.graphicsDataPool) {
|
|
28
|
+
window.PhaserRegistry.graphicsDataPool = [];
|
|
29
|
+
}
|
|
30
|
+
return window.PhaserRegistry.graphicsDataPool;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @param webGL
|
|
36
|
+
* @param type
|
|
37
|
+
*/
|
|
38
|
+
export function switchMode(webGL, type) {
|
|
39
|
+
let webGLData;
|
|
40
|
+
if (!webGL.data.length) {
|
|
41
|
+
webGLData = getGraphicsDataPool().pop() || new GraphicsData(webGL.gl);
|
|
42
|
+
webGLData.mode = type;
|
|
43
|
+
webGL.data.push(webGLData);
|
|
44
|
+
} else {
|
|
45
|
+
webGLData = webGL.data[webGL.data.length - 1];
|
|
46
|
+
if (webGLData.mode !== type || type === 1) {
|
|
47
|
+
webGLData = getGraphicsDataPool().pop() || new GraphicsData(webGL.gl);
|
|
48
|
+
webGLData.mode = type;
|
|
49
|
+
webGL.data.push(webGLData);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
webGLData.dirty = true;
|
|
53
|
+
return webGLData;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param graphicsData
|
|
59
|
+
* @param webGLData
|
|
60
|
+
*/
|
|
61
|
+
export function buildLine(graphicsData, webGLData) {
|
|
62
|
+
// TODO OPTIMISE!
|
|
63
|
+
let i = 0;
|
|
64
|
+
let points = graphicsData.points;
|
|
65
|
+
if (points.length === 0) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
// if the line width is an odd number add 0.5 to align to a whole pixel
|
|
69
|
+
if (graphicsData.lineWidth % 2) {
|
|
70
|
+
for (i = 0; i < points.length; i += 1) {
|
|
71
|
+
points[i] += 0.5;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// get first and last point.. figure out the middle!
|
|
75
|
+
const firstPoint = new Point(points[0], points[1]);
|
|
76
|
+
let lastPoint = new Point(points[points.length - 2], points[points.length - 1]);
|
|
77
|
+
// if the first point is the last point - gonna have issues :)
|
|
78
|
+
if (firstPoint.x === lastPoint.x && firstPoint.y === lastPoint.y) {
|
|
79
|
+
// need to clone as we are going to slightly modify the shape..
|
|
80
|
+
points = points.slice();
|
|
81
|
+
points.pop();
|
|
82
|
+
points.pop();
|
|
83
|
+
lastPoint = new Point(points[points.length - 2], points[points.length - 1]);
|
|
84
|
+
const midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) * 0.5;
|
|
85
|
+
const midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) * 0.5;
|
|
86
|
+
points.unshift(midPointX, midPointY);
|
|
87
|
+
points.push(midPointX, midPointY);
|
|
88
|
+
}
|
|
89
|
+
const verts = webGLData.points;
|
|
90
|
+
const indices = webGLData.indices;
|
|
91
|
+
const length = points.length / 2;
|
|
92
|
+
let indexCount = points.length;
|
|
93
|
+
let indexStart = verts.length / 6;
|
|
94
|
+
// DRAW the Line
|
|
95
|
+
const width = graphicsData.lineWidth / 2;
|
|
96
|
+
// sort color
|
|
97
|
+
const color = hex2rgb(graphicsData.lineColor);
|
|
98
|
+
const alpha = graphicsData.lineAlpha;
|
|
99
|
+
const r = color[0] * alpha;
|
|
100
|
+
const g = color[1] * alpha;
|
|
101
|
+
const b = color[2] * alpha;
|
|
102
|
+
let px;
|
|
103
|
+
let py;
|
|
104
|
+
let p1x;
|
|
105
|
+
let p1y;
|
|
106
|
+
let p2x;
|
|
107
|
+
let p2y;
|
|
108
|
+
let p3x;
|
|
109
|
+
let p3y;
|
|
110
|
+
let perpx;
|
|
111
|
+
let perpy;
|
|
112
|
+
let perp2x;
|
|
113
|
+
let perp2y;
|
|
114
|
+
let perp3x;
|
|
115
|
+
let perp3y;
|
|
116
|
+
let a1;
|
|
117
|
+
let b1;
|
|
118
|
+
let c1;
|
|
119
|
+
let a2;
|
|
120
|
+
let b2;
|
|
121
|
+
let c2;
|
|
122
|
+
let denom;
|
|
123
|
+
let pdist;
|
|
124
|
+
let dist;
|
|
125
|
+
p1x = points[0];
|
|
126
|
+
p1y = points[1];
|
|
127
|
+
p2x = points[2];
|
|
128
|
+
p2y = points[3];
|
|
129
|
+
perpx = -(p1y - p2y);
|
|
130
|
+
perpy = p1x - p2x;
|
|
131
|
+
dist = Math.sqrt((perpx * perpx) + (perpy * perpy));
|
|
132
|
+
perpx /= dist;
|
|
133
|
+
perpy /= dist;
|
|
134
|
+
perpx *= width;
|
|
135
|
+
perpy *= width;
|
|
136
|
+
// start
|
|
137
|
+
verts.push(p1x - perpx, p1y - perpy, r, g, b, alpha);
|
|
138
|
+
verts.push(p1x + perpx, p1y + perpy, r, g, b, alpha);
|
|
139
|
+
for (i = 1; i < length - 1; i += 1) {
|
|
140
|
+
p1x = points[(i - 1) * 2];
|
|
141
|
+
p1y = points[(i - 1) * 2 + 1];
|
|
142
|
+
p2x = points[(i) * 2];
|
|
143
|
+
p2y = points[(i) * 2 + 1];
|
|
144
|
+
p3x = points[(i + 1) * 2];
|
|
145
|
+
p3y = points[(i + 1) * 2 + 1];
|
|
146
|
+
perpx = -(p1y - p2y);
|
|
147
|
+
perpy = p1x - p2x;
|
|
148
|
+
dist = Math.sqrt((perpx * perpx) + (perpy * perpy));
|
|
149
|
+
perpx /= dist;
|
|
150
|
+
perpy /= dist;
|
|
151
|
+
perpx *= width;
|
|
152
|
+
perpy *= width;
|
|
153
|
+
perp2x = -(p2y - p3y);
|
|
154
|
+
perp2y = p2x - p3x;
|
|
155
|
+
dist = Math.sqrt(perp2x * perp2x + perp2y * perp2y);
|
|
156
|
+
perp2x /= dist;
|
|
157
|
+
perp2y /= dist;
|
|
158
|
+
perp2x *= width;
|
|
159
|
+
perp2y *= width;
|
|
160
|
+
a1 = (-perpy + p1y) - (-perpy + p2y);
|
|
161
|
+
b1 = (-perpx + p2x) - (-perpx + p1x);
|
|
162
|
+
c1 = (-perpx + p1x) * (-perpy + p2y) - (-perpx + p2x) * (-perpy + p1y);
|
|
163
|
+
a2 = (-perp2y + p3y) - (-perp2y + p2y);
|
|
164
|
+
b2 = (-perp2x + p2x) - (-perp2x + p3x);
|
|
165
|
+
c2 = (-perp2x + p3x) * (-perp2y + p2y) - (-perp2x + p2x) * (-perp2y + p3y);
|
|
166
|
+
denom = (a1 * b2) - (a2 * b1);
|
|
167
|
+
if (Math.abs(denom) < 0.1) {
|
|
168
|
+
denom += 10.1;
|
|
169
|
+
verts.push(p2x - perpx, p2y - perpy, r, g, b, alpha);
|
|
170
|
+
verts.push(p2x + perpx, p2y + perpy, r, g, b, alpha);
|
|
171
|
+
/* eslint-disable no-continue */
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
px = (b1 * c2 - b2 * c1) / denom;
|
|
175
|
+
py = (a2 * c1 - a1 * c2) / denom;
|
|
176
|
+
pdist = (px - p2x) * (px - p2x) + (py - p2y) + (py - p2y);
|
|
177
|
+
if (pdist > 140 * 140) {
|
|
178
|
+
perp3x = perpx - perp2x;
|
|
179
|
+
perp3y = perpy - perp2y;
|
|
180
|
+
dist = Math.sqrt(perp3x * perp3x + perp3y * perp3y);
|
|
181
|
+
perp3x /= dist;
|
|
182
|
+
perp3y /= dist;
|
|
183
|
+
perp3x *= width;
|
|
184
|
+
perp3y *= width;
|
|
185
|
+
verts.push(p2x - perp3x, p2y - perp3y);
|
|
186
|
+
verts.push(r, g, b, alpha);
|
|
187
|
+
verts.push(p2x + perp3x, p2y + perp3y);
|
|
188
|
+
verts.push(r, g, b, alpha);
|
|
189
|
+
verts.push(p2x - perp3x, p2y - perp3y);
|
|
190
|
+
verts.push(r, g, b, alpha);
|
|
191
|
+
indexCount += 1;
|
|
192
|
+
} else {
|
|
193
|
+
verts.push(px, py);
|
|
194
|
+
verts.push(r, g, b, alpha);
|
|
195
|
+
verts.push(p2x - (px - p2x), p2y - (py - p2y));
|
|
196
|
+
verts.push(r, g, b, alpha);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
p1x = points[(length - 2) * 2];
|
|
200
|
+
p1y = points[(length - 2) * 2 + 1];
|
|
201
|
+
p2x = points[(length - 1) * 2];
|
|
202
|
+
p2y = points[(length - 1) * 2 + 1];
|
|
203
|
+
perpx = -(p1y - p2y);
|
|
204
|
+
perpy = p1x - p2x;
|
|
205
|
+
dist = Math.sqrt((perpx * perpx) + (perpy * perpy));
|
|
206
|
+
perpx /= dist;
|
|
207
|
+
perpy /= dist;
|
|
208
|
+
perpx *= width;
|
|
209
|
+
perpy *= width;
|
|
210
|
+
verts.push(p2x - perpx, p2y - perpy);
|
|
211
|
+
verts.push(r, g, b, alpha);
|
|
212
|
+
verts.push(p2x + perpx, p2y + perpy);
|
|
213
|
+
verts.push(r, g, b, alpha);
|
|
214
|
+
indices.push(indexStart);
|
|
215
|
+
for (i = 0; i < indexCount; i += 1) {
|
|
216
|
+
indices.push(indexStart);
|
|
217
|
+
indexStart += 1;
|
|
218
|
+
}
|
|
219
|
+
indices.push(indexStart - 1);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
*
|
|
224
|
+
* @param graphicsData
|
|
225
|
+
* @param webGLData
|
|
226
|
+
*/
|
|
227
|
+
export function buildRectangle(graphicsData, webGLData) {
|
|
228
|
+
//
|
|
229
|
+
// need to convert points to a nice regular data
|
|
230
|
+
//
|
|
231
|
+
const rectData = graphicsData.shape;
|
|
232
|
+
const x = rectData.x;
|
|
233
|
+
const y = rectData.y;
|
|
234
|
+
const width = rectData.width;
|
|
235
|
+
const height = rectData.height;
|
|
236
|
+
|
|
237
|
+
if (graphicsData.fill) {
|
|
238
|
+
const color = hex2rgb(graphicsData.fillColor);
|
|
239
|
+
const alpha = graphicsData.fillAlpha;
|
|
240
|
+
const r = color[0] * alpha;
|
|
241
|
+
const g = color[1] * alpha;
|
|
242
|
+
const b = color[2] * alpha;
|
|
243
|
+
const verts = webGLData.points;
|
|
244
|
+
const indices = webGLData.indices;
|
|
245
|
+
const vertPos = verts.length / 6;
|
|
246
|
+
// start
|
|
247
|
+
verts.push(x, y);
|
|
248
|
+
verts.push(r, g, b, alpha);
|
|
249
|
+
verts.push(x + width, y);
|
|
250
|
+
verts.push(r, g, b, alpha);
|
|
251
|
+
verts.push(x, y + height);
|
|
252
|
+
verts.push(r, g, b, alpha);
|
|
253
|
+
verts.push(x + width, y + height);
|
|
254
|
+
verts.push(r, g, b, alpha);
|
|
255
|
+
// insert 2 dead triangles..
|
|
256
|
+
indices.push(vertPos, vertPos, vertPos + 1, vertPos + 2, vertPos + 3, vertPos + 3);
|
|
257
|
+
}
|
|
258
|
+
if (graphicsData.lineWidth) {
|
|
259
|
+
const tempPoints = graphicsData.points;
|
|
260
|
+
graphicsData.points = [x, y, x + width, y, x + width, y + height, x, y + height, x, y];
|
|
261
|
+
buildLine(graphicsData, webGLData);
|
|
262
|
+
graphicsData.points = tempPoints;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
*
|
|
268
|
+
* @param fromX
|
|
269
|
+
* @param fromY
|
|
270
|
+
* @param cpX
|
|
271
|
+
* @param cpY
|
|
272
|
+
* @param toX
|
|
273
|
+
* @param toY
|
|
274
|
+
*/
|
|
275
|
+
export function quadraticBezierCurve(fromX, fromY, cpX, cpY, toX, toY) {
|
|
276
|
+
let xa;
|
|
277
|
+
let ya;
|
|
278
|
+
let xb;
|
|
279
|
+
let yb;
|
|
280
|
+
let x;
|
|
281
|
+
let y;
|
|
282
|
+
const n = 20;
|
|
283
|
+
const points = [];
|
|
284
|
+
const getPt = (n1, n2, perc) => {
|
|
285
|
+
const diff = n2 - n1;
|
|
286
|
+
return n1 + (diff * perc);
|
|
287
|
+
};
|
|
288
|
+
let j = 0;
|
|
289
|
+
for (let i = 0; i <= n; i += 1) {
|
|
290
|
+
j = i / n;
|
|
291
|
+
// The Green Line
|
|
292
|
+
xa = getPt(fromX, cpX, j);
|
|
293
|
+
ya = getPt(fromY, cpY, j);
|
|
294
|
+
xb = getPt(cpX, toX, j);
|
|
295
|
+
yb = getPt(cpY, toY, j);
|
|
296
|
+
// The Black Dot
|
|
297
|
+
x = getPt(xa, xb, j);
|
|
298
|
+
y = getPt(ya, yb, j);
|
|
299
|
+
points.push(x, y);
|
|
300
|
+
}
|
|
301
|
+
return points;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
*
|
|
306
|
+
* @param graphicsData
|
|
307
|
+
* @param webGLData
|
|
308
|
+
*/
|
|
309
|
+
export function buildRoundedRectangle(graphicsData, webGLData) {
|
|
310
|
+
const rrectData = graphicsData.shape;
|
|
311
|
+
const x = rrectData.x;
|
|
312
|
+
const y = rrectData.y;
|
|
313
|
+
const width = rrectData.width;
|
|
314
|
+
const height = rrectData.height;
|
|
315
|
+
const radius = rrectData.radius;
|
|
316
|
+
let recPoints = [];
|
|
317
|
+
recPoints.push(x, y + radius);
|
|
318
|
+
recPoints = recPoints.concat(quadraticBezierCurve(x, y + height - radius, x, y + height, x + radius, y + height));
|
|
319
|
+
recPoints = recPoints.concat(quadraticBezierCurve(x + width - radius, y + height, x + width, y + height, x + width, y + height - radius));
|
|
320
|
+
recPoints = recPoints.concat(quadraticBezierCurve(x + width, y + radius, x + width, y, x + width - radius, y));
|
|
321
|
+
recPoints = recPoints.concat(quadraticBezierCurve(x + radius, y, x, y, x, y + radius));
|
|
322
|
+
if (graphicsData.fill) {
|
|
323
|
+
const color = hex2rgb(graphicsData.fillColor);
|
|
324
|
+
const alpha = graphicsData.fillAlpha;
|
|
325
|
+
const r = color[0] * alpha;
|
|
326
|
+
const g = color[1] * alpha;
|
|
327
|
+
const b = color[2] * alpha;
|
|
328
|
+
const verts = webGLData.points;
|
|
329
|
+
const indices = webGLData.indices;
|
|
330
|
+
const vecPos = verts.length / 6;
|
|
331
|
+
const triangles = triangulate(recPoints, null, 2);
|
|
332
|
+
for (let i = 0; i < triangles.length; i += 3) {
|
|
333
|
+
indices.push(triangles[i] + vecPos);
|
|
334
|
+
indices.push(triangles[i] + vecPos);
|
|
335
|
+
indices.push(triangles[i + 1] + vecPos);
|
|
336
|
+
indices.push(triangles[i + 2] + vecPos);
|
|
337
|
+
indices.push(triangles[i + 2] + vecPos);
|
|
338
|
+
}
|
|
339
|
+
for (let i = 0; i < recPoints.length; i += 2) {
|
|
340
|
+
// TODO verify
|
|
341
|
+
verts.push(recPoints[i], recPoints[i + 1], r, g, b, alpha);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (graphicsData.lineWidth) {
|
|
345
|
+
const tempPoints = graphicsData.points;
|
|
346
|
+
graphicsData.points = recPoints;
|
|
347
|
+
buildLine(graphicsData, webGLData);
|
|
348
|
+
graphicsData.points = tempPoints;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
*
|
|
354
|
+
* @param graphicsData
|
|
355
|
+
* @param webGLData
|
|
356
|
+
*/
|
|
357
|
+
export function buildCircle(graphicsData, webGLData) {
|
|
358
|
+
// need to convert points to a nice regular data
|
|
359
|
+
const circleData = graphicsData.shape;
|
|
360
|
+
const x = circleData.x;
|
|
361
|
+
const y = circleData.y;
|
|
362
|
+
let width;
|
|
363
|
+
let height;
|
|
364
|
+
// TODO - bit hacky??
|
|
365
|
+
if (graphicsData.type === GEOM_CIRCLE) {
|
|
366
|
+
width = circleData.radius;
|
|
367
|
+
height = circleData.radius;
|
|
368
|
+
} else {
|
|
369
|
+
width = circleData.width;
|
|
370
|
+
height = circleData.height;
|
|
371
|
+
}
|
|
372
|
+
const totalSegs = 40;
|
|
373
|
+
const seg = (Math.PI * 2) / totalSegs;
|
|
374
|
+
if (graphicsData.fill) {
|
|
375
|
+
const color = hex2rgb(graphicsData.fillColor);
|
|
376
|
+
const alpha = graphicsData.fillAlpha;
|
|
377
|
+
const r = color[0] * alpha;
|
|
378
|
+
const g = color[1] * alpha;
|
|
379
|
+
const b = color[2] * alpha;
|
|
380
|
+
const verts = webGLData.points;
|
|
381
|
+
const indices = webGLData.indices;
|
|
382
|
+
let vecPos = verts.length / 6;
|
|
383
|
+
indices.push(vecPos);
|
|
384
|
+
for (let i = 0; i < totalSegs + 1; i += 1) {
|
|
385
|
+
verts.push(x, y, r, g, b, alpha);
|
|
386
|
+
verts.push(x + Math.sin(seg * i) * width, y + Math.cos(seg * i) * height, r, g, b, alpha);
|
|
387
|
+
indices.push(vecPos, vecPos + 1);
|
|
388
|
+
vecPos += 2;
|
|
389
|
+
}
|
|
390
|
+
indices.push(vecPos - 1);
|
|
391
|
+
}
|
|
392
|
+
if (graphicsData.lineWidth) {
|
|
393
|
+
const tempPoints = graphicsData.points;
|
|
394
|
+
graphicsData.points = [];
|
|
395
|
+
for (let i = 0; i < totalSegs + 1; i += 1) {
|
|
396
|
+
graphicsData.points.push(x + Math.sin(seg * i) * width, y + Math.cos(seg * i) * height);
|
|
397
|
+
}
|
|
398
|
+
buildLine(graphicsData, webGLData);
|
|
399
|
+
graphicsData.points = tempPoints;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
*
|
|
405
|
+
* @param graphicsData
|
|
406
|
+
* @param webGLData
|
|
407
|
+
*/
|
|
408
|
+
export function buildComplexPoly(graphicsData, webGLData) {
|
|
409
|
+
// TODO - no need to copy this as it gets turned into a Float32Array anyways..
|
|
410
|
+
const points = graphicsData.points.slice();
|
|
411
|
+
if (points.length < 6) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
// get first and last point.. figure out the middle!
|
|
415
|
+
const indices = webGLData.indices;
|
|
416
|
+
webGLData.points = points;
|
|
417
|
+
webGLData.alpha = graphicsData.fillAlpha;
|
|
418
|
+
webGLData.color = hex2rgb(graphicsData.fillColor);
|
|
419
|
+
/*
|
|
420
|
+
calculate the bounds..
|
|
421
|
+
*/
|
|
422
|
+
let minX = Infinity;
|
|
423
|
+
let maxX = -Infinity;
|
|
424
|
+
let minY = Infinity;
|
|
425
|
+
let maxY = -Infinity;
|
|
426
|
+
let x;
|
|
427
|
+
let y;
|
|
428
|
+
// get size..
|
|
429
|
+
for (let i = 0; i < points.length; i += 2) {
|
|
430
|
+
x = points[i];
|
|
431
|
+
y = points[i + 1];
|
|
432
|
+
minX = x < minX ? x : minX;
|
|
433
|
+
maxX = x > maxX ? x : maxX;
|
|
434
|
+
minY = y < minY ? y : minY;
|
|
435
|
+
maxY = y > maxY ? y : maxY;
|
|
436
|
+
}
|
|
437
|
+
// add a quad to the end cos there is no point making another buffer!
|
|
438
|
+
points.push(minX, minY, maxX, minY, maxX, maxY, minX, maxY);
|
|
439
|
+
// push a quad onto the end..
|
|
440
|
+
// TODO - this aint needed!
|
|
441
|
+
const length = points.length / 2;
|
|
442
|
+
for (let i = 0; i < length; i += 1) {
|
|
443
|
+
indices.push(i);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
*
|
|
449
|
+
* @param graphicsData
|
|
450
|
+
* @param webGLData
|
|
451
|
+
*/
|
|
452
|
+
export function buildPoly(graphicsData, webGLData) {
|
|
453
|
+
const points = graphicsData.points;
|
|
454
|
+
if (points.length < 6) {
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
// get first and last point.. figure out the middle!
|
|
458
|
+
const verts = webGLData.points;
|
|
459
|
+
const indices = webGLData.indices;
|
|
460
|
+
const length = points.length / 2;
|
|
461
|
+
// sort color
|
|
462
|
+
const color = hex2rgb(graphicsData.fillColor);
|
|
463
|
+
const alpha = graphicsData.fillAlpha;
|
|
464
|
+
const r = color[0] * alpha;
|
|
465
|
+
const g = color[1] * alpha;
|
|
466
|
+
const b = color[2] * alpha;
|
|
467
|
+
const triangles = triangulate(points, null, 2);
|
|
468
|
+
if (!triangles) {
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
471
|
+
const vertPos = verts.length / 6;
|
|
472
|
+
for (let i = 0; i < triangles.length; i += 3) {
|
|
473
|
+
indices.push(triangles[i] + vertPos);
|
|
474
|
+
indices.push(triangles[i] + vertPos);
|
|
475
|
+
indices.push(triangles[i + 1] + vertPos);
|
|
476
|
+
indices.push(triangles[i + 2] + vertPos);
|
|
477
|
+
indices.push(triangles[i + 2] + vertPos);
|
|
478
|
+
}
|
|
479
|
+
for (let i = 0; i < length; i += 1) {
|
|
480
|
+
verts.push(points[i * 2], points[i * 2 + 1], r, g, b, alpha);
|
|
481
|
+
}
|
|
482
|
+
return true;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
*
|
|
487
|
+
* @param graphics
|
|
488
|
+
* @param gl
|
|
489
|
+
*/
|
|
490
|
+
export function updateGraphics(graphics, gl) {
|
|
491
|
+
const stencilBufferLimit = getStencilBufferLimit();
|
|
492
|
+
// get the contexts graphics object
|
|
493
|
+
let webGL = graphics._webGL[gl.id];
|
|
494
|
+
// if the graphics object does not exist in the webGL context time to create it!
|
|
495
|
+
if (!webGL) {
|
|
496
|
+
webGL = { lastIndex: 0, data: [], gl };
|
|
497
|
+
graphics._webGL[gl.id] = webGL;
|
|
498
|
+
}
|
|
499
|
+
// flag the graphics as not dirty as we are about to update it...
|
|
500
|
+
graphics.dirty = false;
|
|
501
|
+
let i;
|
|
502
|
+
// if the user cleared the graphics object we will need to clear every object
|
|
503
|
+
if (graphics.clearDirty) {
|
|
504
|
+
graphics.clearDirty = false;
|
|
505
|
+
// lop through and return all the webGLDatas to the object pool so than can be reused later on
|
|
506
|
+
for (i = 0; i < webGL.data.length; i += 1) {
|
|
507
|
+
const graphicsData = webGL.data[i];
|
|
508
|
+
graphicsData.reset();
|
|
509
|
+
getGraphicsDataPool().push(graphicsData);
|
|
510
|
+
}
|
|
511
|
+
// clear the array and reset the index..
|
|
512
|
+
webGL.data = [];
|
|
513
|
+
webGL.lastIndex = 0;
|
|
514
|
+
}
|
|
515
|
+
let webGLData;
|
|
516
|
+
// loop through the graphics datas and construct each one..
|
|
517
|
+
// if the object is a complex fill then the new stencil buffer technique will be used
|
|
518
|
+
// other wise graphics objects will be pushed into a batch..
|
|
519
|
+
for (i = webGL.lastIndex; i < graphics.graphicsData.length; i += 1) {
|
|
520
|
+
const data = graphics.graphicsData[i];
|
|
521
|
+
if (data.type === GEOM_POLYGON) {
|
|
522
|
+
// need to add the points the the graphics object..
|
|
523
|
+
data.points = data.shape.points.slice();
|
|
524
|
+
if (data.shape.closed) {
|
|
525
|
+
// close the poly if the value is true!
|
|
526
|
+
if (data.points[0] !== data.points[data.points.length - 2] || data.points[1] !== data.points[data.points.length - 1]) {
|
|
527
|
+
data.points.push(data.points[0], data.points[1]);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
// MAKE SURE WE HAVE THE CORRECT TYPE..
|
|
531
|
+
if (data.fill) {
|
|
532
|
+
if (data.points.length >= stencilBufferLimit) {
|
|
533
|
+
if (data.points.length < stencilBufferLimit * 2) {
|
|
534
|
+
webGLData = switchMode(webGL, 0);
|
|
535
|
+
const canDrawUsingSimple = buildPoly(data, webGLData);
|
|
536
|
+
// console.log(canDrawUsingSimple);
|
|
537
|
+
if (!canDrawUsingSimple) {
|
|
538
|
+
// console.log("<>>>")
|
|
539
|
+
webGLData = switchMode(webGL, 1);
|
|
540
|
+
buildComplexPoly(data, webGLData);
|
|
541
|
+
}
|
|
542
|
+
} else {
|
|
543
|
+
webGLData = switchMode(webGL, 1);
|
|
544
|
+
buildComplexPoly(data, webGLData);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if (data.lineWidth > 0) {
|
|
549
|
+
webGLData = switchMode(webGL, 0);
|
|
550
|
+
buildLine(data, webGLData);
|
|
551
|
+
}
|
|
552
|
+
} else {
|
|
553
|
+
webGLData = switchMode(webGL, 0);
|
|
554
|
+
if (data.type === GEOM_RECTANGLE) {
|
|
555
|
+
buildRectangle(data, webGLData);
|
|
556
|
+
} else if (data.type === GEOM_CIRCLE || data.type === GEOM_ELLIPSE) {
|
|
557
|
+
buildCircle(data, webGLData);
|
|
558
|
+
} else if (data.type === GEOM_ROUNDED_RECTANGLE) {
|
|
559
|
+
buildRoundedRectangle(data, webGLData);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
webGL.lastIndex += 1;
|
|
563
|
+
}
|
|
564
|
+
// upload all the dirty data...
|
|
565
|
+
for (i = 0; i < webGL.data.length; i += 1) {
|
|
566
|
+
webGLData = webGL.data[i];
|
|
567
|
+
if (webGLData.dirty) {
|
|
568
|
+
webGLData.upload();
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
*
|
|
575
|
+
* @param graphics
|
|
576
|
+
* @param renderSession
|
|
577
|
+
*/
|
|
578
|
+
export function renderGraphics(graphics, renderSession) {
|
|
579
|
+
const gl = renderSession.gl;
|
|
580
|
+
const projection = renderSession.projection;
|
|
581
|
+
const offset = renderSession.offset;
|
|
582
|
+
let shader = renderSession.shaderManager.primitiveShader;
|
|
583
|
+
let webGLData;
|
|
584
|
+
if (graphics.dirty) {
|
|
585
|
+
updateGraphics(graphics, gl);
|
|
586
|
+
}
|
|
587
|
+
const webGL = graphics._webGL[gl.id];
|
|
588
|
+
// https://github.com/photonstorm/phaser-ce/pull/179
|
|
589
|
+
if (!webGL) {
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
// This could be speeded up for sure!
|
|
593
|
+
for (let i = 0; i < webGL.data.length; i += 1) {
|
|
594
|
+
if (webGL.data[i].mode === 1) {
|
|
595
|
+
webGLData = webGL.data[i];
|
|
596
|
+
renderSession.stencilManager.pushStencil(graphics, webGLData, renderSession);
|
|
597
|
+
// render quad..
|
|
598
|
+
gl.drawElements(gl.TRIANGLE_FAN, 4, gl.UNSIGNED_SHORT, (webGLData.indices.length - 4) * 2);
|
|
599
|
+
renderSession.stencilManager.popStencil(graphics, webGLData, renderSession);
|
|
600
|
+
} else {
|
|
601
|
+
webGLData = webGL.data[i];
|
|
602
|
+
renderSession.shaderManager.setShader(shader); // activatePrimitiveShader();
|
|
603
|
+
shader = renderSession.shaderManager.primitiveShader;
|
|
604
|
+
gl.uniformMatrix3fv(shader.translationMatrix, false, graphics.worldTransform.toArray(true));
|
|
605
|
+
gl.uniform1f(shader.flipY, 1);
|
|
606
|
+
gl.uniform2f(shader.projectionVector, projection.x, -projection.y);
|
|
607
|
+
gl.uniform2f(shader.offsetVector, -offset.x, -offset.y);
|
|
608
|
+
gl.uniform3fv(shader.tintColor, hex2rgb(graphics.tint));
|
|
609
|
+
gl.uniform1f(shader.alpha, graphics.worldAlpha);
|
|
610
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, webGLData.buffer);
|
|
611
|
+
gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 4 * 6, 0);
|
|
612
|
+
gl.vertexAttribPointer(shader.colorAttribute, 4, gl.FLOAT, false, 4 * 6, 2 * 4);
|
|
613
|
+
// set the index buffer!
|
|
614
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webGLData.indexBuffer);
|
|
615
|
+
gl.drawElements(gl.TRIANGLE_STRIP, webGLData.indices.length, gl.UNSIGNED_SHORT, 0);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
export default class {
|
|
9
|
+
|
|
10
|
+
constructor(gl) {
|
|
11
|
+
this.gl = gl;
|
|
12
|
+
// TODO does this need to be split before uploading??
|
|
13
|
+
this.color = [0, 0, 0]; // color split!
|
|
14
|
+
this.points = [];
|
|
15
|
+
this.indices = [];
|
|
16
|
+
this.buffer = gl.createBuffer();
|
|
17
|
+
this.indexBuffer = gl.createBuffer();
|
|
18
|
+
this.mode = 1;
|
|
19
|
+
this.alpha = 1;
|
|
20
|
+
this.dirty = true;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
reset() {
|
|
24
|
+
this.points = [];
|
|
25
|
+
this.indices = [];
|
|
26
|
+
this.glPoints = null;
|
|
27
|
+
this.glIndicies = null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
upload() {
|
|
31
|
+
const gl = this.gl;
|
|
32
|
+
// this.lastIndex = graphics.graphicsData.length;
|
|
33
|
+
this.glPoints = new Float32Array(this.points);
|
|
34
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
|
|
35
|
+
gl.bufferData(gl.ARRAY_BUFFER, this.glPoints, gl.STATIC_DRAW);
|
|
36
|
+
this.glIndicies = new Uint16Array(this.indices);
|
|
37
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
|
38
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.glIndicies, gl.STATIC_DRAW);
|
|
39
|
+
this.dirty = false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
}
|
|
@@ -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 { updateGraphics } from './graphics';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param maskData
|
|
12
|
+
* @param renderSession
|
|
13
|
+
*/
|
|
14
|
+
export function pushMask(maskData, renderSession) {
|
|
15
|
+
const gl = renderSession.gl;
|
|
16
|
+
if (maskData.dirty) {
|
|
17
|
+
updateGraphics(maskData, gl);
|
|
18
|
+
}
|
|
19
|
+
if (maskData._webGL[gl.id] === undefined || maskData._webGL[gl.id].data === undefined || maskData._webGL[gl.id].data.length === 0) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
renderSession.stencilManager.pushStencil(maskData, maskData._webGL[gl.id].data[0], renderSession);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
*
|
|
27
|
+
* @param maskData
|
|
28
|
+
* @param renderSession
|
|
29
|
+
*/
|
|
30
|
+
export function popMask(maskData, renderSession) {
|
|
31
|
+
const gl = renderSession.gl;
|
|
32
|
+
if (maskData._webGL[gl.id] === undefined || maskData._webGL[gl.id].data === undefined || maskData._webGL[gl.id].data.length === 0) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
renderSession.stencilManager.popStencil(maskData, maskData._webGL[gl.id].data[0], renderSession);
|
|
36
|
+
}
|