Phaser.Renderer.WebGL.GameObjects.Graphics = { TYPES: [Phaser.GameObject.Graphics.prototype] , circleSegments: 40, graphicsDataPool: [] , render: function (renderer, src){ if (src.visible === false || src.alpha === 0 || src.isMask === true ) { return ; } if (src._cacheAsBitmap) { if (src.dirty || src.cachedSpriteDirty) { src._generateCachedSprite(); src.updateCachedSpriteTexture(); src.cachedSpriteDirty = false ; src.dirty = false ; } src._cachedSprite.worldAlpha = src.worldAlpha; return ; } renderer.spriteBatch.stop(); renderer.setBlendMode(src.blendMode); if (src._mask) { renderer.pushMask(src._mask); } if (src._filters) { renderer.filterManager.pushFilter(src._filterBlock); } if (src.blendMode !== renderer.spriteBatch.currentBlendMode) { renderer.spriteBatch.currentBlendMode = src.blendMode; var blendModeWebGL = renderer.blendModes[renderer.spriteBatch.currentBlendMode]; renderer.spriteBatch.gl.blendFunc(blendModeWebGL[0], blendModeWebGL[1]); } if (src.webGLDirty) { src.dirty = true ; src.webGLDirty = false ; } var gl = renderer.gl; var offset = renderer.offset; var projection = renderer.projection; var shader = renderer.shaderManager.primitiveShader; var webGLData; if (src.dirty) { Phaser.Renderer.WebGL.GameObjects.Graphics.updateGraphics(renderer, src); } for (var i = 0; i < _AN_Read_length('length', src._webGL.data); i++ ){ webGLData = src._webGL.data[i]; if (webGLData.mode === 1) { renderer.stencilManager.pushStencil(src, webGLData); gl.drawElements(gl.TRIANGLE_FAN, 4, gl.UNSIGNED_SHORT, (_AN_Read_length('length', webGLData.indices) - 4) * 2); renderer.stencilManager.popStencil(src, webGLData); } else { renderer.shaderManager.setShader(shader); gl.uniformMatrix3fv(shader.translationMatrix, false , src.worldTransform.toArray(true )); gl.uniform1f(shader.flipY, 1); gl.uniform2f(shader.projectionVector, projection.x, - projection.y); gl.uniform2f(shader.offsetVector, - offset.x, - offset.y); gl.uniform3fv(shader.tintColor, Phaser.Color.hexToRGBArray(src.tint)); gl.uniform1f(shader.alpha, src.worldAlpha); gl.bindBuffer(gl.ARRAY_BUFFER, webGLData.buffer); gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false , 4 * 6, 0); gl.vertexAttribPointer(shader.colorAttribute, 4, gl.FLOAT, false , 4 * 6, 2 * 4); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webGLData.indexBuffer); gl.drawElements(gl.TRIANGLE_STRIP, _AN_Read_length('length', webGLData.indices), gl.UNSIGNED_SHORT, 0); } } if (src.children.length) { renderer.spriteBatch.start(); for (var i = 0; i < _AN_Read_length('length', src.children); i++ ){ var child = src.children[i]; child.render(renderer, child); } renderer.spriteBatch.stop(); } if (src._filters) { renderer.filterManager.popFilter(); } if (src._mask) { renderer.popMask(src.mask); } renderer.drawCount++ ; renderer.spriteBatch.start(); } , updateGraphics: function (renderer, graphics){ var gl = renderer.gl; var webGL = graphics._webGL; if (!webGL) { webGL = graphics._webGL = { lastIndex: 0, data: [] , gl: gl} ; } graphics.dirty = false ; var i; if (graphics.clearDirty) { graphics.clearDirty = false ; for (i = 0; i < _AN_Read_length('length', webGL.data); i++ ){ var graphicsData = webGL.data[i]; graphicsData.reset(); Phaser.Renderer.WebGL.GameObjects.Graphics.graphicsDataPool.push(graphicsData); } webGL.data = [] ; webGL.lastIndex = 0; } var webGLData; for (i = webGL.lastIndex; i < _AN_Read_length('length', graphics.graphicsData); i++ ){ var data = graphics.graphicsData[i]; switch (data.type){ case Phaser.RECTANGLE: webGLData = Phaser.Renderer.WebGL.GameObjects.Graphics.switchMode(webGL, 0); Phaser.Renderer.WebGL.GameObjects.Graphics.buildRectangle(data, webGLData); break ; case Phaser.CIRCLE: case Phaser.ELLIPSE: webGLData = Phaser.Renderer.WebGL.GameObjects.Graphics.switchMode(webGL, 0); Phaser.Renderer.WebGL.GameObjects.Graphics.buildCircle(data, webGLData); break ; case Phaser.ROUNDEDRECTANGLE: webGLData = Phaser.Renderer.WebGL.GameObjects.Graphics.switchMode(webGL, 0); Phaser.Renderer.WebGL.GameObjects.Graphics.buildRoundedRectangle(data, webGLData); break ; case Phaser.POLYGON: data.points = data.shape.points.slice(); if (data.shape.closed) { if (data.points[0] !== data.points[_AN_Read_length('length', data.points) - 2] || data.points[1] !== data.points[_AN_Read_length('length', data.points) - 1]) { data.points.push(data.points[0], data.points[1]); } } if (data.fill) { if (_AN_Read_length('length', data.points) >= renderer.stencilBufferLimit) { if (_AN_Read_length('length', data.points) < renderer.stencilBufferLimit * 2) { webGLData = Phaser.Renderer.WebGL.GameObjects.Graphics.switchMode(webGL, 0); var canDrawUsingSimple = Phaser.Renderer.WebGL.GameObjects.Graphics.buildPoly(data, webGLData); if (!canDrawUsingSimple) { webGLData = Phaser.Renderer.WebGL.GameObjects.Graphics.switchMode(webGL, 1); Phaser.Renderer.WebGL.GameObjects.Graphics.buildComplexPoly(data, webGLData); } } else { webGLData = Phaser.Renderer.WebGL.GameObjects.Graphics.switchMode(webGL, 1); Phaser.Renderer.WebGL.GameObjects.Graphics.buildComplexPoly(data, webGLData); } } } if (data.lineWidth > 0) { webGLData = Phaser.Renderer.WebGL.GameObjects.Graphics.switchMode(webGL, 0); Phaser.Renderer.WebGL.GameObjects.Graphics.buildLine(data, webGLData); } break ; } webGL.lastIndex++ ; } for (i = 0; i < _AN_Read_length('length', webGL.data); i++ ){ webGLData = webGL.data[i]; if (webGLData.dirty) { webGLData.upload(); } } } , switchMode: function (webGL, type){ var webGLData; if (!_AN_Read_length('length', webGL.data)) { webGLData = Phaser.Renderer.WebGL.GameObjects.Graphics.graphicsDataPool.pop() || new Phaser.Renderer.WebGL.GameObjects.GraphicsData(webGL.gl); webGLData.mode = type; webGL.data.push(webGLData); } else { webGLData = webGL.data[_AN_Read_length('length', webGL.data) - 1]; if (webGLData.mode !== type || type === 1) { webGLData = Phaser.Renderer.WebGL.GameObjects.Graphics.graphicsDataPool.pop() || new Phaser.Renderer.WebGL.GameObjects.GraphicsData(webGL.gl); webGLData.mode = type; webGL.data.push(webGLData); } } webGLData.dirty = true ; return webGLData; } , buildRectangle: function (graphicsData, webGLData){ var rectData = graphicsData.shape; var x = rectData.x; var y = rectData.y; var width = rectData.width; var height = rectData.height; if (graphicsData.fill) { var color = Phaser.Color.hexToRGBArray(graphicsData.fillColor); var alpha = graphicsData.fillAlpha; var r = color[0] * alpha; var g = color[1] * alpha; var b = color[2] * alpha; var verts = webGLData.points; var indices = webGLData.indices; var vertPos = _AN_Read_length('length', verts) / 6; verts.push(x, y); verts.push(r, g, b, alpha); verts.push(x + width, y); verts.push(r, g, b, alpha); verts.push(x, y + height); verts.push(r, g, b, alpha); verts.push(x + width, y + height); verts.push(r, g, b, alpha); indices.push(vertPos, vertPos, vertPos + 1, vertPos + 2, vertPos + 3, vertPos + 3); } if (graphicsData.lineWidth) { var tempPoints = graphicsData.points; graphicsData.points = [x, y, x + width, y, x + width, y + height, x, y + height, x, y] ; Phaser.Renderer.WebGL.GameObjects.Graphics.buildLine(graphicsData, webGLData); graphicsData.points = tempPoints; } } , buildRoundedRectangle: function (graphicsData, webGLData){ var rrectData = graphicsData.shape; var x = rrectData.x; var y = rrectData.y; var width = rrectData.width; var height = rrectData.height; var radius = rrectData.radius; var recPoints = [] ; recPoints.push(x, y + radius); recPoints = recPoints.concat(Phaser.Renderer.WebGL.GameObjects.Graphics.quadraticBezierCurve(x, y + height - radius, x, y + height, x + radius, y + height)); recPoints = recPoints.concat(Phaser.Renderer.WebGL.GameObjects.Graphics.quadraticBezierCurve(x + width - radius, y + height, x + width, y + height, x + width, y + height - radius)); recPoints = recPoints.concat(Phaser.Renderer.WebGL.GameObjects.Graphics.quadraticBezierCurve(x + width, y + radius, x + width, y, x + width - radius, y)); recPoints = recPoints.concat(Phaser.Renderer.WebGL.GameObjects.Graphics.quadraticBezierCurve(x + radius, y, x, y, x, y + radius)); if (graphicsData.fill) { var color = Phaser.Color.hexToRGBArray(graphicsData.fillColor); var alpha = graphicsData.fillAlpha; var r = color[0] * alpha; var g = color[1] * alpha; var b = color[2] * alpha; var verts = webGLData.points; var indices = webGLData.indices; var vecPos = _AN_Read_length('length', verts) / 6; var triangles = Phaser.EarCut.Triangulate(recPoints, null , 2); var i = 0; for (i = 0; i < _AN_Read_length('length', triangles); i += 3){ indices.push(triangles[i] + vecPos); indices.push(triangles[i] + vecPos); indices.push(triangles[i + 1] + vecPos); indices.push(triangles[i + 2] + vecPos); indices.push(triangles[i + 2] + vecPos); } for (i = 0; i < _AN_Read_length('length', recPoints); i++ ){ verts.push(recPoints[i], recPoints[++i], r, g, b, alpha); } } if (graphicsData.lineWidth) { var tempPoints = graphicsData.points; graphicsData.points = recPoints; Phaser.Renderer.WebGL.GameObjects.Graphics.buildLine(graphicsData, webGLData); graphicsData.points = tempPoints; } } , quadraticBezierCurve: function (fromX, fromY, cpX, cpY, toX, toY){ var xa; var ya; var xb; var yb; var x; var y; var n = 20; var points = [] ; function getPt(n1, n2, perc){ var diff = n2 - n1; return n1 + (diff * perc); } ; var j = 0; for (var i = 0; i <= n; i++ ){ j = i / n; xa = getPt(fromX, cpX, j); ya = getPt(fromY, cpY, j); xb = getPt(cpX, toX, j); yb = getPt(cpY, toY, j); x = getPt(xa, xb, j); y = getPt(ya, yb, j); points.push(x, y); } return points; } , buildCircle: function (graphicsData, webGLData){ var circleData = graphicsData.shape; var x = circleData.x; var y = circleData.y; var width; var height; if (graphicsData.type === Phaser.CIRCLE) { width = circleData.radius; height = circleData.radius; } else { width = circleData.width; height = circleData.height; } var totalSegs = Phaser.Renderer.WebGL.GameObjects.Graphics.circleSegments; var seg = (Math.PI * 2) / totalSegs; var i = 0; if (graphicsData.fill) { var color = Phaser.Color.hexToRGBArray(graphicsData.fillColor); var alpha = graphicsData.fillAlpha; var r = color[0] * alpha; var g = color[1] * alpha; var b = color[2] * alpha; var verts = webGLData.points; var indices = webGLData.indices; var vecPos = _AN_Read_length('length', verts) / 6; indices.push(vecPos); for (i = 0; i < totalSegs + 1; i++ ){ verts.push(x, y, r, g, b, alpha); verts.push(x + Math.sin(seg * i) * width, y + Math.cos(seg * i) * height, r, g, b, alpha); indices.push(vecPos++ , vecPos++ ); } indices.push(vecPos - 1); } if (graphicsData.lineWidth) { var tempPoints = graphicsData.points; graphicsData.points = [] ; for (i = 0; i < totalSegs + 1; i++ ){ graphicsData.points.push(x + Math.sin(seg * i) * width, y + Math.cos(seg * i) * height); } Phaser.Renderer.WebGL.GameObjects.Graphics.buildLine(graphicsData, webGLData); graphicsData.points = tempPoints; } } , buildLine: function (graphicsData, webGLData){ var i = 0; var points = graphicsData.points; if (_AN_Read_length('length', points) === 0) { return ; } if (graphicsData.lineWidth % 2) { for (i = 0; i < _AN_Read_length('length', points); i++ ){ points[i] += 0.5; } } var firstPoint = new Phaser.Point(points[0], points[1]); var lastPoint = new Phaser.Point(points[(_AN_Read_length('length', points)) - 2], points[(_AN_Read_length('length', points)) - 1]); if (firstPoint.x === lastPoint.x && firstPoint.y === lastPoint.y) { points = points.slice(); points.pop(); points.pop(); lastPoint = new Phaser.Point(points[(_AN_Read_length('length', points)) - 2], points[(_AN_Read_length('length', points)) - 1]); var midPointX = lastPoint.x + (firstPoint.x - lastPoint.x) * 0.5; var midPointY = lastPoint.y + (firstPoint.y - lastPoint.y) * 0.5; points.unshift(midPointX, midPointY); points.push(midPointX, midPointY); } var verts = webGLData.points; var indices = webGLData.indices; var length = _AN_Read_length('length', points) / 2; var indexCount = _AN_Read_length('length', points); var indexStart = _AN_Read_length('length', verts) / 6; var width = graphicsData.lineWidth / 2; var color = Phaser.Color.hexToRGBArray(graphicsData.lineColor); var alpha = graphicsData.lineAlpha; var r = color[0] * alpha; var g = color[1] * alpha; var b = color[2] * alpha; var px, py, p1x, p1y, p2x, p2y, p3x, p3y; var perpx, perpy, perp2x, perp2y, perp3x, perp3y; var a1, b1, c1, a2, b2, c2; var denom, pdist, dist; p1x = points[0]; p1y = points[1]; p2x = points[2]; p2y = points[3]; perpx = - (p1y - p2y); perpy = p1x - p2x; dist = Math.sqrt(perpx * perpx + perpy * perpy); perpx /= dist; perpy /= dist; perpx *= width; perpy *= width; verts.push(p1x - perpx, p1y - perpy, r, g, b, alpha); verts.push(p1x + perpx, p1y + perpy, r, g, b, alpha); for (i = 1; i < length - 1; i++ ){ p1x = points[(i - 1) * 2]; p1y = points[(i - 1) * 2 + 1]; p2x = points[(i) * 2]; p2y = points[(i) * 2 + 1]; p3x = points[(i + 1) * 2]; p3y = points[(i + 1) * 2 + 1]; perpx = - (p1y - p2y); perpy = p1x - p2x; dist = Math.sqrt(perpx * perpx + perpy * perpy); perpx /= dist; perpy /= dist; perpx *= width; perpy *= width; perp2x = - (p2y - p3y); perp2y = p2x - p3x; dist = Math.sqrt(perp2x * perp2x + perp2y * perp2y); perp2x /= dist; perp2y /= dist; perp2x *= width; perp2y *= width; a1 = (- perpy + p1y) - (- perpy + p2y); b1 = (- perpx + p2x) - (- perpx + p1x); c1 = (- perpx + p1x) * (- perpy + p2y) - (- perpx + p2x) * (- perpy + p1y); a2 = (- perp2y + p3y) - (- perp2y + p2y); b2 = (- perp2x + p2x) - (- perp2x + p3x); c2 = (- perp2x + p3x) * (- perp2y + p2y) - (- perp2x + p2x) * (- perp2y + p3y); denom = a1 * b2 - a2 * b1; if (Math.abs(denom) < 0.1) { denom += 10.1; verts.push(p2x - perpx, p2y - perpy, r, g, b, alpha); verts.push(p2x + perpx, p2y + perpy, r, g, b, alpha); continue ; } px = (b1 * c2 - b2 * c1) / denom; py = (a2 * c1 - a1 * c2) / denom; pdist = (px - p2x) * (px - p2x) + (py - p2y) + (py - p2y); if (pdist > 140 * 140) { perp3x = perpx - perp2x; perp3y = perpy - perp2y; dist = Math.sqrt(perp3x * perp3x + perp3y * perp3y); perp3x /= dist; perp3y /= dist; perp3x *= width; perp3y *= width; verts.push(p2x - perp3x, p2y - perp3y, r, g, b, alpha); verts.push(p2x + perp3x, p2y + perp3y, r, g, b, alpha); verts.push(p2x - perp3x, p2y - perp3y, r, g, b, alpha); indexCount++ ; } else { verts.push(px, py, r, g, b, alpha); verts.push(p2x - (px - p2x), p2y - (py - p2y), r, g, b, alpha); } } p1x = points[(length - 2) * 2]; p1y = points[(length - 2) * 2 + 1]; p2x = points[(length - 1) * 2]; p2y = points[(length - 1) * 2 + 1]; perpx = - (p1y - p2y); perpy = p1x - p2x; dist = Math.sqrt(perpx * perpx + perpy * perpy); perpx /= dist; perpy /= dist; perpx *= width; perpy *= width; verts.push(p2x - perpx, p2y - perpy, r, g, b, alpha); verts.push(p2x + perpx, p2y + perpy, r, g, b, alpha); indices.push(indexStart); for (i = 0; i < indexCount; i++ ){ indices.push(indexStart++ ); } indices.push(indexStart - 1); } , buildComplexPoly: function (graphicsData, webGLData){ var points = graphicsData.points.slice(); if (_AN_Read_length('length', points) < 6) { return ; } var indices = webGLData.indices; webGLData.points = points; webGLData.alpha = graphicsData.fillAlpha; webGLData.color = Phaser.Color.hexToRGBArray(graphicsData.fillColor); var minX = Infinity; var maxX = - Infinity; var minY = Infinity; var maxY = - Infinity; var x; var y; for (var i = 0; i < _AN_Read_length('length', points); i += 2){ x = points[i]; y = points[i + 1]; minX = (x < minX)? x: minX; maxX = (x > maxX)? x: maxX; minY = (y < minY)? y: minY; maxY = (y > maxY)? y: maxY; } points.push(minX, minY, maxX, minY, maxX, maxY, minX, maxY); var length = _AN_Read_length('length', points) / 2; for (i = 0; i < length; i++ ){ indices.push(i); } } , buildPoly: function (graphicsData, webGLData){ var points = graphicsData.points; if (_AN_Read_length('length', points) < 6) { return ; } var verts = webGLData.points; var indices = webGLData.indices; var length = _AN_Read_length('length', points) / 2; var color = Phaser.Color.hexToRGBArray(graphicsData.fillColor); var alpha = graphicsData.fillAlpha; var r = color[0] * alpha; var g = color[1] * alpha; var b = color[2] * alpha; var triangles = Phaser.EarCut.Triangulate(points, null , 2); if (!triangles) { return false ; } var vertPos = _AN_Read_length('length', verts) / 6; var i = 0; for (i = 0; i < _AN_Read_length('length', triangles); i += 3){ indices.push(triangles[i] + vertPos); indices.push(triangles[i] + vertPos); indices.push(triangles[i + 1] + vertPos); indices.push(triangles[i + 2] + vertPos); indices.push(triangles[i + 2] + vertPos); } for (i = 0; i < length; i++ ){ verts.push(points[i * 2], points[i * 2 + 1], r, g, b, alpha); } return true ; } } ;