@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,723 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Andras Csizmadia <andras@vpmedia.hu>
|
|
3
|
+
* @author Richard Davey <rich@photonstorm.com>
|
|
4
|
+
* @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
|
|
5
|
+
*/
|
|
6
|
+
import DisplayObject from './display_object';
|
|
7
|
+
import Image from './image';
|
|
8
|
+
import Rectangle from '../geom/rectangle';
|
|
9
|
+
import RoundedRectangle from '../geom/rounded_rectangle';
|
|
10
|
+
import Polygon from '../geom/polygon';
|
|
11
|
+
import Circle from '../geom/circle';
|
|
12
|
+
import Ellipse from '../geom/ellipse';
|
|
13
|
+
import Point from '../geom/point';
|
|
14
|
+
import GraphicsData from './graphics_data';
|
|
15
|
+
import CanvasBuffer from './canvas/buffer';
|
|
16
|
+
import { textureFromCanvas } from './webgl/texture_util';
|
|
17
|
+
import { renderGraphics as renderCanvasGraphics } from './canvas/graphics';
|
|
18
|
+
import { renderGraphics as renderWebGLGraphics } from './webgl/graphics';
|
|
19
|
+
import { renderCanvas as renderSpriteCanvas, renderWebGL as renderSpriteWebGL } from './sprite_util';
|
|
20
|
+
import { getEmptyRectangle } from '../geom/util/rectangle';
|
|
21
|
+
import { getIdentityMatrix } from '../geom/util/matrix';
|
|
22
|
+
import { BLEND_NORMAL, GRAPHICS, GEOM_POLYGON, GEOM_CIRCLE, GEOM_ELLIPSE, GEOM_RECTANGLE, GEOM_ROUNDED_RECTANGLE } from '../core/const';
|
|
23
|
+
|
|
24
|
+
export default class extends DisplayObject {
|
|
25
|
+
|
|
26
|
+
constructor(game, x = 0, y = 0) {
|
|
27
|
+
super();
|
|
28
|
+
this.game = game;
|
|
29
|
+
this.type = GRAPHICS;
|
|
30
|
+
this.position.set(x, y);
|
|
31
|
+
this.renderable = true;
|
|
32
|
+
this.fillAlpha = 1;
|
|
33
|
+
this.lineWidth = 0;
|
|
34
|
+
this.lineColor = 0;
|
|
35
|
+
this.graphicsData = [];
|
|
36
|
+
this.tint = 0xFFFFFF;
|
|
37
|
+
this.blendMode = BLEND_NORMAL;
|
|
38
|
+
this.currentPath = null;
|
|
39
|
+
this._webGL = [];
|
|
40
|
+
this.isMask = false;
|
|
41
|
+
this.boundsPadding = 0;
|
|
42
|
+
this._localBounds = new Rectangle(0, 0, 1, 1);
|
|
43
|
+
this.dirty = true;
|
|
44
|
+
this._boundsDirty = false;
|
|
45
|
+
this.webGLDirty = false;
|
|
46
|
+
this.cachedSpriteDirty = false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
destroy() {
|
|
50
|
+
// TODO
|
|
51
|
+
this.clear();
|
|
52
|
+
super.destroy();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
lineStyle(lineWidth = 0, color = 0, alpha = 1) {
|
|
56
|
+
this.lineWidth = lineWidth || 0;
|
|
57
|
+
this.lineColor = color || 0;
|
|
58
|
+
this.lineAlpha = (alpha === undefined) ? 1 : alpha;
|
|
59
|
+
if (this.currentPath) {
|
|
60
|
+
if (this.currentPath.shape.points.length) {
|
|
61
|
+
// halfway through a line? start a new one!
|
|
62
|
+
this.drawShape(new Polygon(this.currentPath.shape.points.slice(-2)));
|
|
63
|
+
} else {
|
|
64
|
+
// otherwise its empty so lets just set the line properties
|
|
65
|
+
this.currentPath.lineWidth = this.lineWidth;
|
|
66
|
+
this.currentPath.lineColor = this.lineColor;
|
|
67
|
+
this.currentPath.lineAlpha = this.lineAlpha;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
moveTo(x, y) {
|
|
74
|
+
this.drawShape(new Polygon([x, y]));
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
lineTo(x, y) {
|
|
79
|
+
if (!this.currentPath) {
|
|
80
|
+
this.moveTo(0, 0);
|
|
81
|
+
}
|
|
82
|
+
this.currentPath.shape.points.push(x, y);
|
|
83
|
+
this.dirty = true;
|
|
84
|
+
this._boundsDirty = true;
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
quadraticCurveTo(cpX, cpY, toX, toY) {
|
|
89
|
+
if (this.currentPath) {
|
|
90
|
+
if (this.currentPath.shape.points.length === 0) {
|
|
91
|
+
this.currentPath.shape.points = [0, 0];
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
this.moveTo(0, 0);
|
|
95
|
+
}
|
|
96
|
+
let xa;
|
|
97
|
+
let ya;
|
|
98
|
+
const n = 20;
|
|
99
|
+
const points = this.currentPath.shape.points;
|
|
100
|
+
if (points.length === 0) {
|
|
101
|
+
this.moveTo(0, 0);
|
|
102
|
+
}
|
|
103
|
+
const fromX = points[points.length - 2];
|
|
104
|
+
const fromY = points[points.length - 1];
|
|
105
|
+
let j = 0;
|
|
106
|
+
for (let i = 1; i <= n; i += 1) {
|
|
107
|
+
j = i / n;
|
|
108
|
+
xa = fromX + ((cpX - fromX) * j);
|
|
109
|
+
ya = fromY + ((cpY - fromY) * j);
|
|
110
|
+
points.push(xa + (((cpX + ((toX - cpX) * j)) - xa) * j), ya + (((cpY + ((toY - cpY) * j)) - ya) * j));
|
|
111
|
+
}
|
|
112
|
+
this.dirty = true;
|
|
113
|
+
this._boundsDirty = true;
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
bezierCurveTo(cpX, cpY, cpX2, cpY2, toX, toY) {
|
|
118
|
+
if (this.currentPath) {
|
|
119
|
+
if (this.currentPath.shape.points.length === 0) {
|
|
120
|
+
this.currentPath.shape.points = [0, 0];
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
this.moveTo(0, 0);
|
|
124
|
+
}
|
|
125
|
+
const n = 20;
|
|
126
|
+
let dt;
|
|
127
|
+
let dt2;
|
|
128
|
+
let dt3;
|
|
129
|
+
let t2;
|
|
130
|
+
let t3;
|
|
131
|
+
const points = this.currentPath.shape.points;
|
|
132
|
+
const fromX = points[points.length - 2];
|
|
133
|
+
const fromY = points[points.length - 1];
|
|
134
|
+
let j = 0;
|
|
135
|
+
for (let i = 1; i <= n; i += 1) {
|
|
136
|
+
j = i / n;
|
|
137
|
+
dt = (1 - j);
|
|
138
|
+
dt2 = dt * dt;
|
|
139
|
+
dt3 = dt2 * dt;
|
|
140
|
+
t2 = j * j;
|
|
141
|
+
t3 = t2 * j;
|
|
142
|
+
points.push(dt3 * fromX + 3 * dt2 * j * cpX + 3 * dt * t2 * cpX2 + t3 * toX, dt3 * fromY + 3 * dt2 * j * cpY + 3 * dt * t2 * cpY2 + t3 * toY);
|
|
143
|
+
}
|
|
144
|
+
this.dirty = true;
|
|
145
|
+
this._boundsDirty = true;
|
|
146
|
+
return this;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
arcTo(x1, y1, x2, y2, radius) {
|
|
150
|
+
if (this.currentPath) {
|
|
151
|
+
if (this.currentPath.shape.points.length === 0) {
|
|
152
|
+
this.currentPath.shape.points.push(x1, y1);
|
|
153
|
+
}
|
|
154
|
+
} else {
|
|
155
|
+
this.moveTo(x1, y1);
|
|
156
|
+
}
|
|
157
|
+
const points = this.currentPath.shape.points;
|
|
158
|
+
const fromX = points[points.length - 2];
|
|
159
|
+
const fromY = points[points.length - 1];
|
|
160
|
+
const a1 = fromY - y1;
|
|
161
|
+
const b1 = fromX - x1;
|
|
162
|
+
const a2 = y2 - y1;
|
|
163
|
+
const b2 = x2 - x1;
|
|
164
|
+
const mm = Math.abs(a1 * b2 - b1 * a2);
|
|
165
|
+
if (mm < 1.0e-8 || radius === 0) {
|
|
166
|
+
if (points[points.length - 2] !== x1 || points[points.length - 1] !== y1) {
|
|
167
|
+
points.push(x1, y1);
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
const dd = a1 * a1 + b1 * b1;
|
|
171
|
+
const cc = a2 * a2 + b2 * b2;
|
|
172
|
+
const tt = a1 * a2 + b1 * b2;
|
|
173
|
+
const k1 = radius * Math.sqrt(dd) / mm;
|
|
174
|
+
const k2 = radius * Math.sqrt(cc) / mm;
|
|
175
|
+
const j1 = k1 * tt / dd;
|
|
176
|
+
const j2 = k2 * tt / cc;
|
|
177
|
+
const cx = k1 * b2 + k2 * b1;
|
|
178
|
+
const cy = k1 * a2 + k2 * a1;
|
|
179
|
+
const px = b1 * (k2 + j1);
|
|
180
|
+
const py = a1 * (k2 + j1);
|
|
181
|
+
const qx = b2 * (k1 + j2);
|
|
182
|
+
const qy = a2 * (k1 + j2);
|
|
183
|
+
const startAngle = Math.atan2(py - cy, px - cx);
|
|
184
|
+
const endAngle = Math.atan2(qy - cy, qx - cx);
|
|
185
|
+
this.arc(cx + x1, cy + y1, radius, startAngle, endAngle, b1 * a2 > b2 * a1);
|
|
186
|
+
}
|
|
187
|
+
this.dirty = true;
|
|
188
|
+
this._boundsDirty = true;
|
|
189
|
+
return this;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
arc(cx, cy, radius, startAngle, endAngle, anticlockwise = false, segments = 40) {
|
|
193
|
+
// If we do this we can never draw a full circle
|
|
194
|
+
if (startAngle === endAngle) {
|
|
195
|
+
return this;
|
|
196
|
+
}
|
|
197
|
+
if (!anticlockwise && endAngle <= startAngle) {
|
|
198
|
+
endAngle += Math.PI * 2;
|
|
199
|
+
} else if (anticlockwise && startAngle <= endAngle) {
|
|
200
|
+
startAngle += Math.PI * 2;
|
|
201
|
+
}
|
|
202
|
+
const sweep = anticlockwise ? (startAngle - endAngle) * -1 : (endAngle - startAngle);
|
|
203
|
+
const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * segments;
|
|
204
|
+
// Sweep check - moved here because we don't want to do the moveTo below if the arc fails
|
|
205
|
+
if (sweep === 0) {
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
const startX = cx + Math.cos(startAngle) * radius;
|
|
209
|
+
const startY = cy + Math.sin(startAngle) * radius;
|
|
210
|
+
if (anticlockwise && this.filling) {
|
|
211
|
+
this.moveTo(cx, cy);
|
|
212
|
+
} else {
|
|
213
|
+
this.moveTo(startX, startY);
|
|
214
|
+
}
|
|
215
|
+
// currentPath will always exist after calling a moveTo
|
|
216
|
+
const points = this.currentPath.shape.points;
|
|
217
|
+
const theta = sweep / (segs * 2);
|
|
218
|
+
const theta2 = theta * 2;
|
|
219
|
+
const cTheta = Math.cos(theta);
|
|
220
|
+
const sTheta = Math.sin(theta);
|
|
221
|
+
const segMinus = segs - 1;
|
|
222
|
+
const remainder = (segMinus % 1) / segMinus;
|
|
223
|
+
for (let i = 0; i <= segMinus; i += 1) {
|
|
224
|
+
const real = i + remainder * i;
|
|
225
|
+
const angle = ((theta) + startAngle + (theta2 * real));
|
|
226
|
+
const c = Math.cos(angle);
|
|
227
|
+
const s = -Math.sin(angle);
|
|
228
|
+
points.push(((cTheta * c) + (sTheta * s)) * radius + cx, ((cTheta * -s) + (sTheta * c)) * radius + cy);
|
|
229
|
+
}
|
|
230
|
+
this.dirty = true;
|
|
231
|
+
this._boundsDirty = true;
|
|
232
|
+
return this;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
beginFill(color = 0, alpha = 1) {
|
|
236
|
+
this.filling = true;
|
|
237
|
+
this.fillColor = color || 0;
|
|
238
|
+
this.fillAlpha = (alpha === undefined) ? 1 : alpha;
|
|
239
|
+
if (this.currentPath) {
|
|
240
|
+
if (this.currentPath.shape.points.length <= 2) {
|
|
241
|
+
this.currentPath.fill = this.filling;
|
|
242
|
+
this.currentPath.fillColor = this.fillColor;
|
|
243
|
+
this.currentPath.fillAlpha = this.fillAlpha;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return this;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
endFill() {
|
|
250
|
+
this.filling = false;
|
|
251
|
+
this.fillColor = null;
|
|
252
|
+
this.fillAlpha = 1;
|
|
253
|
+
return this;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
drawRect(x, y, width, height) {
|
|
257
|
+
this.drawShape(new Rectangle(x, y, width, height));
|
|
258
|
+
return this;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
drawRoundedRect(x, y, width, height, radius) {
|
|
262
|
+
this.drawShape(new RoundedRectangle(x, y, width, height, radius));
|
|
263
|
+
return this;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
drawCircle(x, y, diameter) {
|
|
267
|
+
this.drawShape(new Circle(x, y, diameter));
|
|
268
|
+
return this;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
drawEllipse(x, y, width, height) {
|
|
272
|
+
this.drawShape(new Ellipse(x, y, width, height));
|
|
273
|
+
return this;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
drawPolygon(path) {
|
|
277
|
+
let points;
|
|
278
|
+
if (path instanceof Polygon) {
|
|
279
|
+
points = path.points;
|
|
280
|
+
} else {
|
|
281
|
+
points = path;
|
|
282
|
+
}
|
|
283
|
+
// TODO
|
|
284
|
+
/*
|
|
285
|
+
if (!Array.isArray(points)) {
|
|
286
|
+
points = new Array(arguments.length);
|
|
287
|
+
for (let i = 0; i < points.length; i += 1) {
|
|
288
|
+
points[i] = arguments[i];
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
*/
|
|
292
|
+
this.drawShape(new Polygon(points));
|
|
293
|
+
return this;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
clear() {
|
|
297
|
+
this.lineWidth = 0;
|
|
298
|
+
this.filling = false;
|
|
299
|
+
this.dirty = true;
|
|
300
|
+
this._boundsDirty = true;
|
|
301
|
+
this.clearDirty = true;
|
|
302
|
+
this.graphicsData = [];
|
|
303
|
+
this.updateLocalBounds();
|
|
304
|
+
return this;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
generateTexture() {
|
|
308
|
+
// TODO
|
|
309
|
+
console.warn('graphics.generateTexture() is not implemented');
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
renderWebGL(renderSession) {
|
|
313
|
+
// if the sprite is not visible or the alpha is 0 then no need to render this element
|
|
314
|
+
if (this.visible === false || this.alpha === 0 || this.isMask === true) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
if (this._cacheAsBitmap) {
|
|
318
|
+
if (this.dirty || this.cachedSpriteDirty) {
|
|
319
|
+
this.generateCachedSprite();
|
|
320
|
+
// we will also need to update the texture on the gpu too!
|
|
321
|
+
this.updateCachedSpriteTexture();
|
|
322
|
+
this.cachedSpriteDirty = false;
|
|
323
|
+
this.dirty = false;
|
|
324
|
+
}
|
|
325
|
+
this._cachedSprite.worldAlpha = this.worldAlpha;
|
|
326
|
+
renderSpriteWebGL.call(this._cachedSprite, renderSession);
|
|
327
|
+
} else {
|
|
328
|
+
renderSession.spriteBatch.stop();
|
|
329
|
+
renderSession.blendModeManager.setBlendMode(this.blendMode);
|
|
330
|
+
if (this._mask) {
|
|
331
|
+
renderSession.maskManager.pushMask(this._mask, renderSession);
|
|
332
|
+
}
|
|
333
|
+
if (this._filters) {
|
|
334
|
+
renderSession.filterManager.pushFilter(this._filterBlock);
|
|
335
|
+
}
|
|
336
|
+
// check blend mode
|
|
337
|
+
if (this.blendMode !== renderSession.spriteBatch.currentBlendMode) {
|
|
338
|
+
renderSession.spriteBatch.currentBlendMode = this.blendMode;
|
|
339
|
+
const blendModeWebGL = window.PhaserRegistry.blendModesWebGL[renderSession.spriteBatch.currentBlendMode];
|
|
340
|
+
renderSession.spriteBatch.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]);
|
|
341
|
+
}
|
|
342
|
+
// check if the webgl graphic needs to be updated
|
|
343
|
+
if (this.webGLDirty) {
|
|
344
|
+
this.dirty = true;
|
|
345
|
+
this.webGLDirty = false;
|
|
346
|
+
}
|
|
347
|
+
renderWebGLGraphics(this, renderSession);
|
|
348
|
+
// only render if it has children!
|
|
349
|
+
if (this.children.length) {
|
|
350
|
+
renderSession.spriteBatch.start();
|
|
351
|
+
// simple render children!
|
|
352
|
+
for (let i = 0; i < this.children.length; i += 1) {
|
|
353
|
+
this.children[i].renderWebGL(renderSession);
|
|
354
|
+
}
|
|
355
|
+
renderSession.spriteBatch.stop();
|
|
356
|
+
}
|
|
357
|
+
if (this._filters) {
|
|
358
|
+
renderSession.filterManager.popFilter();
|
|
359
|
+
}
|
|
360
|
+
if (this._mask) {
|
|
361
|
+
renderSession.maskManager.popMask(this.mask, renderSession);
|
|
362
|
+
}
|
|
363
|
+
renderSession.drawCount += 1;
|
|
364
|
+
renderSession.spriteBatch.start();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
renderCanvas(renderSession) {
|
|
369
|
+
// if the sprite is not visible or the alpha is 0 then no need to render this element
|
|
370
|
+
if (this.visible === false || this.alpha === 0 || this.isMask === true) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
// if the tint has changed, set the graphics object to dirty.
|
|
374
|
+
if (this._prevTint !== this.tint) {
|
|
375
|
+
this.dirty = true;
|
|
376
|
+
this._prevTint = this.tint;
|
|
377
|
+
}
|
|
378
|
+
if (this._cacheAsBitmap) {
|
|
379
|
+
if (this.dirty || this.cachedSpriteDirty) {
|
|
380
|
+
this.generateCachedSprite();
|
|
381
|
+
// we will also need to update the texture
|
|
382
|
+
this.updateCachedSpriteTexture();
|
|
383
|
+
this.cachedSpriteDirty = false;
|
|
384
|
+
this.dirty = false;
|
|
385
|
+
}
|
|
386
|
+
this._cachedSprite.alpha = this.alpha;
|
|
387
|
+
renderSpriteCanvas(this._cachedSprite, renderSession);
|
|
388
|
+
} else {
|
|
389
|
+
const context = renderSession.context;
|
|
390
|
+
const transform = this.worldTransform;
|
|
391
|
+
if (this.blendMode !== renderSession.currentBlendMode) {
|
|
392
|
+
renderSession.currentBlendMode = this.blendMode;
|
|
393
|
+
context.globalCompositeOperation = window.PhaserRegistry.blendModesCanvas[renderSession.currentBlendMode];
|
|
394
|
+
}
|
|
395
|
+
if (this._mask) {
|
|
396
|
+
renderSession.maskManager.pushMask(this._mask, renderSession);
|
|
397
|
+
}
|
|
398
|
+
const resolution = renderSession.resolution;
|
|
399
|
+
const tx = (transform.tx * renderSession.resolution) + renderSession.shakeX;
|
|
400
|
+
const ty = (transform.ty * renderSession.resolution) + renderSession.shakeY;
|
|
401
|
+
context.setTransform(
|
|
402
|
+
transform.a * resolution,
|
|
403
|
+
transform.b * resolution,
|
|
404
|
+
transform.c * resolution,
|
|
405
|
+
transform.d * resolution,
|
|
406
|
+
tx,
|
|
407
|
+
ty,
|
|
408
|
+
);
|
|
409
|
+
renderCanvasGraphics(this, context);
|
|
410
|
+
// simple render children!
|
|
411
|
+
for (let i = 0; i < this.children.length; i += 1) {
|
|
412
|
+
this.children[i].renderCanvas(renderSession);
|
|
413
|
+
}
|
|
414
|
+
if (this._mask) {
|
|
415
|
+
renderSession.maskManager.popMask(renderSession);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
getBounds(matrix = null) {
|
|
421
|
+
if (!this.renderable) {
|
|
422
|
+
return getEmptyRectangle();
|
|
423
|
+
}
|
|
424
|
+
if (this.dirty) {
|
|
425
|
+
this.updateLocalBounds();
|
|
426
|
+
this.webGLDirty = true;
|
|
427
|
+
this.cachedSpriteDirty = true;
|
|
428
|
+
this.dirty = false;
|
|
429
|
+
} else if (this.currentBounds) {
|
|
430
|
+
return this.currentBounds;
|
|
431
|
+
}
|
|
432
|
+
const bounds = this._localBounds;
|
|
433
|
+
const w0 = bounds.x;
|
|
434
|
+
const w1 = bounds.width + bounds.x;
|
|
435
|
+
const h0 = bounds.y;
|
|
436
|
+
const h1 = bounds.height + bounds.y;
|
|
437
|
+
const worldTransform = matrix || this.worldTransform;
|
|
438
|
+
const a = worldTransform.a;
|
|
439
|
+
const b = worldTransform.b;
|
|
440
|
+
const c = worldTransform.c;
|
|
441
|
+
const d = worldTransform.d;
|
|
442
|
+
const tx = worldTransform.tx;
|
|
443
|
+
const ty = worldTransform.ty;
|
|
444
|
+
const x1 = a * w1 + c * h1 + tx;
|
|
445
|
+
const y1 = d * h1 + b * w1 + ty;
|
|
446
|
+
const x2 = a * w0 + c * h1 + tx;
|
|
447
|
+
const y2 = d * h1 + b * w0 + ty;
|
|
448
|
+
const x3 = a * w0 + c * h0 + tx;
|
|
449
|
+
const y3 = d * h0 + b * w0 + ty;
|
|
450
|
+
const x4 = a * w1 + c * h0 + tx;
|
|
451
|
+
const y4 = d * h0 + b * w1 + ty;
|
|
452
|
+
let maxX = x1;
|
|
453
|
+
let maxY = y1;
|
|
454
|
+
let minX = x1;
|
|
455
|
+
let minY = y1;
|
|
456
|
+
minX = x2 < minX ? x2 : minX;
|
|
457
|
+
minX = x3 < minX ? x3 : minX;
|
|
458
|
+
minX = x4 < minX ? x4 : minX;
|
|
459
|
+
minY = y2 < minY ? y2 : minY;
|
|
460
|
+
minY = y3 < minY ? y3 : minY;
|
|
461
|
+
minY = y4 < minY ? y4 : minY;
|
|
462
|
+
maxX = x2 > maxX ? x2 : maxX;
|
|
463
|
+
maxX = x3 > maxX ? x3 : maxX;
|
|
464
|
+
maxX = x4 > maxX ? x4 : maxX;
|
|
465
|
+
maxY = y2 > maxY ? y2 : maxY;
|
|
466
|
+
maxY = y3 > maxY ? y3 : maxY;
|
|
467
|
+
maxY = y4 > maxY ? y4 : maxY;
|
|
468
|
+
this.cachedBounds.x = minX;
|
|
469
|
+
this.cachedBounds.width = maxX - minX;
|
|
470
|
+
this.cachedBounds.y = minY;
|
|
471
|
+
this.cachedBounds.height = maxY - minY;
|
|
472
|
+
this.currentBounds = this.cachedBounds;
|
|
473
|
+
return this.currentBounds;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
getLocalBounds() {
|
|
477
|
+
const matrixCache = this.worldTransform;
|
|
478
|
+
this.worldTransform = getIdentityMatrix();
|
|
479
|
+
for (let i = 0; i < this.children.length; i += 1) {
|
|
480
|
+
this.children[i].updateTransform();
|
|
481
|
+
}
|
|
482
|
+
const bounds = this.getBounds();
|
|
483
|
+
this.worldTransform = matrixCache;
|
|
484
|
+
for (let i = 0; i < this.children.length; i += 1) {
|
|
485
|
+
this.children[i].updateTransform();
|
|
486
|
+
}
|
|
487
|
+
return bounds;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
containsPoint(point, tempPoint) {
|
|
491
|
+
this.worldTransform.applyInverse(point, tempPoint);
|
|
492
|
+
const graphicsData = this.graphicsData;
|
|
493
|
+
for (let i = 0; i < graphicsData.length; i += 0) {
|
|
494
|
+
const data = graphicsData[i];
|
|
495
|
+
if (data.fill && data.shape) {
|
|
496
|
+
if (data.shape.contains(tempPoint.x, tempPoint.y)) {
|
|
497
|
+
return true;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
updateLocalBounds() {
|
|
505
|
+
let minX = Infinity;
|
|
506
|
+
let maxX = -Infinity;
|
|
507
|
+
let minY = Infinity;
|
|
508
|
+
let maxY = -Infinity;
|
|
509
|
+
if (this.graphicsData.length) {
|
|
510
|
+
let shape;
|
|
511
|
+
let points;
|
|
512
|
+
let x;
|
|
513
|
+
let y;
|
|
514
|
+
let w;
|
|
515
|
+
let h;
|
|
516
|
+
for (let i = 0; i < this.graphicsData.length; i += 1) {
|
|
517
|
+
const data = this.graphicsData[i];
|
|
518
|
+
const type = data.type;
|
|
519
|
+
const lineWidth = data.lineWidth;
|
|
520
|
+
shape = data.shape;
|
|
521
|
+
if (type === GEOM_RECTANGLE || type === GEOM_ROUNDED_RECTANGLE) {
|
|
522
|
+
x = shape.x - lineWidth / 2;
|
|
523
|
+
y = shape.y - lineWidth / 2;
|
|
524
|
+
w = shape.width + lineWidth;
|
|
525
|
+
h = shape.height + lineWidth;
|
|
526
|
+
minX = x < minX ? x : minX;
|
|
527
|
+
maxX = x + w > maxX ? x + w : maxX;
|
|
528
|
+
minY = y < minY ? y : minY;
|
|
529
|
+
maxY = y + h > maxY ? y + h : maxY;
|
|
530
|
+
} else if (type === GEOM_CIRCLE) {
|
|
531
|
+
x = shape.x;
|
|
532
|
+
y = shape.y;
|
|
533
|
+
w = shape.radius + lineWidth / 2;
|
|
534
|
+
h = shape.radius + lineWidth / 2;
|
|
535
|
+
minX = x - w < minX ? x - w : minX;
|
|
536
|
+
maxX = x + w > maxX ? x + w : maxX;
|
|
537
|
+
minY = y - h < minY ? y - h : minY;
|
|
538
|
+
maxY = y + h > maxY ? y + h : maxY;
|
|
539
|
+
} else if (type === GEOM_ELLIPSE) {
|
|
540
|
+
x = shape.x;
|
|
541
|
+
y = shape.y;
|
|
542
|
+
w = shape.width + lineWidth / 2;
|
|
543
|
+
h = shape.height + lineWidth / 2;
|
|
544
|
+
minX = x - w < minX ? x - w : minX;
|
|
545
|
+
maxX = x + w > maxX ? x + w : maxX;
|
|
546
|
+
minY = y - h < minY ? y - h : minY;
|
|
547
|
+
maxY = y + h > maxY ? y + h : maxY;
|
|
548
|
+
} else {
|
|
549
|
+
// POLY - assumes points are sequential, not Point objects
|
|
550
|
+
points = shape.points;
|
|
551
|
+
for (let j = 0; j < points.length; j += 1) {
|
|
552
|
+
if (points[j] instanceof Point) {
|
|
553
|
+
x = points[j].x;
|
|
554
|
+
y = points[j].y;
|
|
555
|
+
} else {
|
|
556
|
+
x = points[j];
|
|
557
|
+
y = points[j + 1];
|
|
558
|
+
if (j < points.length - 1) {
|
|
559
|
+
j += 1;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
minX = x - lineWidth < minX ? x - lineWidth : minX;
|
|
563
|
+
maxX = x + lineWidth > maxX ? x + lineWidth : maxX;
|
|
564
|
+
minY = y - lineWidth < minY ? y - lineWidth : minY;
|
|
565
|
+
maxY = y + lineWidth > maxY ? y + lineWidth : maxY;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
} else {
|
|
570
|
+
minX = 0;
|
|
571
|
+
maxX = 0;
|
|
572
|
+
minY = 0;
|
|
573
|
+
maxY = 0;
|
|
574
|
+
}
|
|
575
|
+
const padding = this.boundsPadding;
|
|
576
|
+
this._localBounds.x = minX - padding;
|
|
577
|
+
this._localBounds.width = (maxX - minX) + padding * 2;
|
|
578
|
+
this._localBounds.y = minY - padding;
|
|
579
|
+
this._localBounds.height = (maxY - minY) + padding * 2;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
generateCachedSprite() {
|
|
583
|
+
const bounds = this.getLocalBounds();
|
|
584
|
+
if (!this._cachedSprite) {
|
|
585
|
+
const canvasBuffer = new CanvasBuffer(bounds.width, bounds.height);
|
|
586
|
+
const texture = textureFromCanvas(canvasBuffer.canvas);
|
|
587
|
+
this._cachedSprite = new Image(this.game, 0, 0, texture);
|
|
588
|
+
this._cachedSprite.buffer = canvasBuffer;
|
|
589
|
+
this._cachedSprite.worldTransform = this.worldTransform;
|
|
590
|
+
} else {
|
|
591
|
+
this._cachedSprite.buffer.resize(bounds.width, bounds.height);
|
|
592
|
+
}
|
|
593
|
+
// leverage the anchor to account for the offset of the element
|
|
594
|
+
this._cachedSprite.anchor.x = -(bounds.x / bounds.width);
|
|
595
|
+
this._cachedSprite.anchor.y = -(bounds.y / bounds.height);
|
|
596
|
+
// this._cachedSprite.buffer.context.save();
|
|
597
|
+
this._cachedSprite.buffer.context.translate(-bounds.x, -bounds.y);
|
|
598
|
+
// make sure we set the alpha of the graphics to 1 for the render..
|
|
599
|
+
this.worldAlpha = 1;
|
|
600
|
+
// now render the graphic..
|
|
601
|
+
renderCanvasGraphics(this, this._cachedSprite.buffer.context);
|
|
602
|
+
this._cachedSprite.alpha = this.alpha;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
updateCachedSpriteTexture() {
|
|
606
|
+
const cachedSprite = this._cachedSprite;
|
|
607
|
+
const texture = cachedSprite.texture;
|
|
608
|
+
const canvas = cachedSprite.buffer.canvas;
|
|
609
|
+
texture.baseTexture.width = canvas.width;
|
|
610
|
+
texture.baseTexture.height = canvas.height;
|
|
611
|
+
texture.crop.width = canvas.width;
|
|
612
|
+
texture.crop.height = canvas.height;
|
|
613
|
+
texture.frame.width = canvas.width;
|
|
614
|
+
texture.frame.height = canvas.height;
|
|
615
|
+
cachedSprite._width = canvas.width;
|
|
616
|
+
cachedSprite._height = canvas.height;
|
|
617
|
+
// update the dirty base textures
|
|
618
|
+
texture.baseTexture.dirty();
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
destroyCachedSprite() {
|
|
622
|
+
if (!this._cachedSprite) {
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
this._cachedSprite.texture.destroy(true);
|
|
626
|
+
this._cachedSprite = null;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
drawShape(shape) {
|
|
630
|
+
if (this.currentPath) {
|
|
631
|
+
// check current path!
|
|
632
|
+
if (this.currentPath.shape.points.length <= 2) {
|
|
633
|
+
this.graphicsData.pop();
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
this.currentPath = null;
|
|
637
|
+
// Handle mixed-type polygons
|
|
638
|
+
if (shape instanceof Polygon) {
|
|
639
|
+
shape = shape.clone();
|
|
640
|
+
shape.flatten();
|
|
641
|
+
}
|
|
642
|
+
const data = new GraphicsData(this.lineWidth, this.lineColor, this.lineAlpha, this.fillColor, this.fillAlpha, this.filling, shape);
|
|
643
|
+
this.graphicsData.push(data);
|
|
644
|
+
if (data.type === GEOM_POLYGON) {
|
|
645
|
+
data.shape.closed = this.filling;
|
|
646
|
+
this.currentPath = data;
|
|
647
|
+
}
|
|
648
|
+
this.dirty = true;
|
|
649
|
+
this._boundsDirty = true;
|
|
650
|
+
return data;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
postUpdate() {
|
|
654
|
+
if (this._boundsDirty) {
|
|
655
|
+
this.updateLocalBounds();
|
|
656
|
+
this._boundsDirty = false;
|
|
657
|
+
}
|
|
658
|
+
for (let i = 0; i < this.children.length; i += 1) {
|
|
659
|
+
this.children[i].postUpdate();
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
drawTriangle(points, cull = false) {
|
|
664
|
+
const triangle = new Polygon(points);
|
|
665
|
+
if (cull) {
|
|
666
|
+
const cameraToFace = new Point(0 - points[0].x, 0 - points[0].y);
|
|
667
|
+
const ab = new Point(points[1].x - points[0].x, points[1].y - points[0].y);
|
|
668
|
+
const cb = new Point(points[1].x - points[2].x, points[1].y - points[2].y);
|
|
669
|
+
const faceNormal = cb.cross(ab);
|
|
670
|
+
if (cameraToFace.dot(faceNormal) > 0) {
|
|
671
|
+
this.drawPolygon(triangle);
|
|
672
|
+
}
|
|
673
|
+
} else {
|
|
674
|
+
this.drawPolygon(triangle);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
drawTriangles(vertices, indices, cull = false) {
|
|
679
|
+
const point1 = new Point();
|
|
680
|
+
const point2 = new Point();
|
|
681
|
+
const point3 = new Point();
|
|
682
|
+
let points = [];
|
|
683
|
+
let i;
|
|
684
|
+
if (!indices) {
|
|
685
|
+
if (vertices[0] instanceof Point) {
|
|
686
|
+
for (i = 0; i < vertices.length / 3; i += 1) {
|
|
687
|
+
this.drawTriangle([vertices[i * 3], vertices[i * 3 + 1], vertices[i * 3 + 2]], cull);
|
|
688
|
+
}
|
|
689
|
+
} else {
|
|
690
|
+
for (i = 0; i < vertices.length / 6; i += 1) {
|
|
691
|
+
point1.x = vertices[i * 6 + 0];
|
|
692
|
+
point1.y = vertices[i * 6 + 1];
|
|
693
|
+
point2.x = vertices[i * 6 + 2];
|
|
694
|
+
point2.y = vertices[i * 6 + 3];
|
|
695
|
+
point3.x = vertices[i * 6 + 4];
|
|
696
|
+
point3.y = vertices[i * 6 + 5];
|
|
697
|
+
this.drawTriangle([point1, point2, point3], cull);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
} else if (vertices[0] instanceof Point) {
|
|
701
|
+
for (i = 0; i < indices.length / 3; i += 1) {
|
|
702
|
+
points.push(vertices[indices[i * 3]]);
|
|
703
|
+
points.push(vertices[indices[i * 3 + 1]]);
|
|
704
|
+
points.push(vertices[indices[i * 3 + 2]]);
|
|
705
|
+
if (points.length === 3) {
|
|
706
|
+
this.drawTriangle(points, cull);
|
|
707
|
+
points = [];
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
} else {
|
|
711
|
+
for (i = 0; i < indices.length; i += 1) {
|
|
712
|
+
point1.x = vertices[indices[i] * 2];
|
|
713
|
+
point1.y = vertices[indices[i] * 2 + 1];
|
|
714
|
+
points.push(point1.copyTo({}));
|
|
715
|
+
if (points.length === 3) {
|
|
716
|
+
this.drawTriangle(points, cull);
|
|
717
|
+
points = [];
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
}
|