var BlendModes = require('../../renderer/BlendModes'); var Camera = require('../../cameras/2d/BaseCamera'); var CanvasPool = require('../../display/canvas/CanvasPool'); var Class = require('../../utils/Class'); var Components = require('../components'); var CONST = require('../../const'); var Frame = require('../../textures/Frame'); var GameObject = require('../GameObject'); var Render = require('./RenderTextureRender'); var Utils = require('../../renderer/webgl/Utils'); var UUID = require('../../utils/string/UUID'); var RenderTexture = new Class({ Extends: GameObject, Mixins: [Components.Alpha, Components.BlendMode, Components.ComputedSize, Components.Crop, Components.Depth, Components.Flip, Components.GetBounds, Components.Mask, Components.Origin, Components.Pipeline, Components.ScrollFactor, Components.Tint, Components.Transform, Components.Visible, Render] , initialize: function RenderTexture(scene, x, y, width, height, key, frame){ if (x === undefined) { x = 0; } if (y === undefined) { y = 0; } if (width === undefined) { width = 32; } if (height === undefined) { height = 32; } GameObject.call(this, scene, 'RenderTexture'); this.renderer = scene.sys.game.renderer; this.textureManager = scene.sys.textures; this.globalTint = 16777215; this.globalAlpha = 1; this.canvas = null ; this.framebuffer = null ; this.dirty = false ; this._crop = this.resetCropObject(); this.texture = null ; this.frame = null ; this._saved = false ; if (key === undefined) { this.canvas = CanvasPool.create2D(this, width, height); this.texture = scene.sys.textures.addCanvas(UUID(), this.canvas); this.frame = this.texture.get(); } else { this.texture = scene.sys.textures.get(key); this.frame = this.texture.get(frame); this.canvas = this.frame.source.image; this._saved = true ; this.dirty = true ; this.width = this.frame.cutWidth; this.height = this.frame.cutHeight; } this.context = this.canvas.getContext('2d'); this._eraseMode = false ; this.camera = new Camera(0, 0, width, height); this.gl = null ; this.glTexture = null ; var renderer = this.renderer; if (renderer.type === CONST.WEBGL) { var gl = renderer.gl; this.gl = gl; this.glTexture = this.frame.source.glTexture; this.drawGameObject = this.batchGameObjectWebGL; this.framebuffer = renderer.createFramebuffer(width, height, this.glTexture, false ); } else if (renderer.type === CONST.CANVAS) { this.drawGameObject = this.batchGameObjectCanvas; } this.camera.setScene(scene); this.setPosition(x, y); if (key === undefined) { this.setSize(width, height); } this.setOrigin(0, 0); this.initPipeline(); } , setSize: function (width, height){ return this.resize(width, height); } , resize: function (width, height){ if (height === undefined) { height = width; } if (width !== this.width || height !== this.height) { if (this.frame.name === '__BASE') { this.canvas.width = width; this.canvas.height = height; if (this.gl) { var gl = this.gl; this.renderer.deleteTexture(this.frame.source.glTexture); this.renderer.deleteFramebuffer(this.framebuffer); var glTexture = this.renderer.createTexture2D(0, gl.NEAREST, gl.NEAREST, gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, gl.RGBA, null , width, height, false ); this.framebuffer = this.renderer.createFramebuffer(width, height, glTexture, false ); this.frame.source.isRenderTexture = true ; this.frame.glTexture = glTexture; this.glTexture = glTexture; } this.frame.source.width = width; this.frame.source.height = height; this.camera.setSize(width, height); this.frame.setSize(width, height); this.width = width; this.height = height; } } else { var baseFrame = this.texture.getSourceImage(); if (this.frame.cutX + width > baseFrame.width) { width = baseFrame.width - this.frame.cutX; } if (this.frame.cutY + height > baseFrame.height) { height = baseFrame.height - this.frame.cutY; } this.frame.setSize(width, height, this.frame.cutX, this.frame.cutY); } return this; } , setGlobalTint: function (tint){ this.globalTint = tint; return this; } , setGlobalAlpha: function (alpha){ this.globalAlpha = alpha; return this; } , saveTexture: function (key){ this.textureManager.renameTexture(this.texture.key, key); this._saved = true ; return this.texture; } , fill: function (rgb, alpha, x, y, width, height){ if (alpha === undefined) { alpha = 1; } if (x === undefined) { x = 0; } if (y === undefined) { y = 0; } if (width === undefined) { width = this.frame.cutWidth; } if (height === undefined) { height = this.frame.cutHeight; } var r = ((rgb >> 16) | 0) & 255; var g = ((rgb >> 8) | 0) & 255; var b = (rgb | 0) & 255; var gl = this.gl; var frame = this.frame; if (gl) { var renderer = this.renderer; var bounds = this.getBounds(); renderer.setFramebuffer(this.framebuffer, true ); if (width !== frame.source.width || height !== frame.source.height) { gl.scissor(x + frame.cutX, y + frame.cutY, width, height); } this.pipeline.drawFillRect(bounds.x, bounds.y, bounds.right, bounds.bottom, Utils.getTintFromFloats(r / 255, g / 255, b / 255, 1), alpha); if (width !== frame.source.width || height !== frame.source.height) { gl.scissor(0, 0, frame.source.width, frame.source.height); } this.renderer.setFramebuffer(null , true ); } else { this.context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')'; this.context.fillRect(x + frame.cutX, y + frame.cutY, width, height); } return this; } , clear: function (){ if (this.dirty) { var gl = this.gl; if (gl) { var renderer = this.renderer; renderer.setFramebuffer(this.framebuffer, true ); if (this.frame.cutWidth !== this.canvas.width || this.frame.cutHeight !== this.canvas.height) { gl.scissor(this.frame.cutX, this.frame.cutY, this.frame.cutWidth, this.frame.cutHeight); } gl.clearColor(0, 0, 0, 0); _AN_Call_clear('clear', gl, gl.COLOR_BUFFER_BIT); renderer.setFramebuffer(null , true ); } else { var ctx = this.context; ctx.save(); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(this.frame.cutX, this.frame.cutY, this.frame.cutWidth, this.frame.cutHeight); ctx.restore(); } this.dirty = false ; } return this; } , erase: function (entries, x, y){ this._eraseMode = true ; var blendMode = this.renderer.currentBlendMode; this.renderer.setBlendMode(BlendModes.ERASE); this.draw(entries, x, y, 1, 16777215); this.renderer.setBlendMode(blendMode); this._eraseMode = false ; return this; } , draw: function (entries, x, y, alpha, tint){ if (alpha === undefined) { alpha = this.globalAlpha; } if (tint === undefined) { tint = (this.globalTint >> 16) + (this.globalTint & 65280) + ((this.globalTint & 255) << 16); } else { tint = (tint >> 16) + (tint & 65280) + ((tint & 255) << 16); } if (!Array.isArray(entries)) { entries = [entries] ; } var gl = this.gl; this.camera.preRender(1, 1); if (gl) { var cx = this.camera._cx; var cy = this.camera._cy; var cw = this.camera._cw; var ch = this.camera._ch; this.renderer.setFramebuffer(this.framebuffer, false ); this.renderer.pushScissor(cx, cy, cw, ch, ch); var pipeline = this.pipeline; pipeline.projOrtho(0, this.texture.width, 0, this.texture.height, -1000, 1000); this.batchList(entries, x, y, alpha, tint); pipeline.flush(); this.renderer.setFramebuffer(null , false ); this.renderer.popScissor(); pipeline.projOrtho(0, pipeline.width, pipeline.height, 0, -1000, 1000); } else { this.renderer.setContext(this.context); this.batchList(entries, x, y, alpha, tint); this.renderer.setContext(); } this.dirty = true ; return this; } , drawFrame: function (key, frame, x, y, alpha, tint){ if (x === undefined) { x = 0; } if (y === undefined) { y = 0; } if (alpha === undefined) { alpha = this.globalAlpha; } if (tint === undefined) { tint = (this.globalTint >> 16) + (this.globalTint & 65280) + ((this.globalTint & 255) << 16); } else { tint = (tint >> 16) + (tint & 65280) + ((tint & 255) << 16); } var gl = this.gl; var textureFrame = this.textureManager.getFrame(key, frame); if (textureFrame) { this.camera.preRender(1, 1); if (gl) { var cx = this.camera._cx; var cy = this.camera._cy; var cw = this.camera._cw; var ch = this.camera._ch; this.renderer.setFramebuffer(this.framebuffer, false ); this.renderer.pushScissor(cx, cy, cw, ch, ch); var pipeline = this.pipeline; pipeline.projOrtho(0, this.texture.width, 0, this.texture.height, -1000, 1000); pipeline.batchTextureFrame(textureFrame, x + this.frame.cutX, y + this.frame.cutY, tint, alpha, this.camera.matrix, null ); pipeline.flush(); this.renderer.setFramebuffer(null , false ); this.renderer.popScissor(); pipeline.projOrtho(0, pipeline.width, pipeline.height, 0, -1000, 1000); } else { this.batchTextureFrame(textureFrame, x + this.frame.cutX, y + this.frame.cutY, alpha, tint); } this.dirty = true ; } return this; } , batchList: function (children, x, y, alpha, tint){ for (var i = 0; i < (_AN_Read_length('length', children)); i++ ){ var entry = children[i]; if (!entry || entry === this) { continue ; } if (entry.renderWebGL || entry.renderCanvas) { this.drawGameObject(entry, x, y); } else if (entry.isParent || entry.list) { this.batchGroup(entry.getChildren(), x, y); } else if (typeof entry === 'string') { this.batchTextureFrameKey(entry, null , x, y, alpha, tint); } else if (entry instanceof Frame) { this.batchTextureFrame(entry, x, y, alpha, tint); } else if (Array.isArray(entry)) { this.batchList(entry, x, y, alpha, tint); } } } , batchGroup: function (children, x, y){ if (x === undefined) { x = 0; } if (y === undefined) { y = 0; } x += this.frame.cutX; y += this.frame.cutY; for (var i = 0; i < (_AN_Read_length('length', children)); i++ ){ var entry = children[i]; if (entry.willRender()) { var tx = entry.x + x; var ty = entry.y + y; this.drawGameObject(entry, tx, ty); } } } , batchGameObjectWebGL: function (gameObject, x, y){ if (x === undefined) { x = gameObject.x; } if (y === undefined) { y = gameObject.y; } var prevX = gameObject.x; var prevY = gameObject.y; if (!this._eraseMode) { this.renderer.setBlendMode(gameObject.blendMode); } gameObject.setPosition(x + this.frame.cutX, y + this.frame.cutY); gameObject.renderWebGL(this.renderer, gameObject, 0, this.camera, null ); gameObject.setPosition(prevX, prevY); } , batchGameObjectCanvas: function (gameObject, x, y){ if (x === undefined) { x = gameObject.x; } if (y === undefined) { y = gameObject.y; } var prevX = gameObject.x; var prevY = gameObject.y; if (this._eraseMode) { var blendMode = gameObject.blendMode; gameObject.blendMode = BlendModes.ERASE; } gameObject.setPosition(x + this.frame.cutX, y + this.frame.cutY); gameObject.renderCanvas(this.renderer, gameObject, 0, this.camera, null ); gameObject.setPosition(prevX, prevY); if (this._eraseMode) { gameObject.blendMode = blendMode; } } , batchTextureFrameKey: function (key, frame, x, y, alpha, tint){ var textureFrame = this.textureManager.getFrame(key, frame); if (textureFrame) { this.batchTextureFrame(textureFrame, x, y, alpha, tint); } } , batchTextureFrame: function (textureFrame, x, y, alpha, tint){ if (x === undefined) { x = 0; } if (y === undefined) { y = 0; } x += this.frame.cutX; y += this.frame.cutY; if (this.gl) { this.pipeline.batchTextureFrame(textureFrame, x, y, tint, alpha, this.camera.matrix, null ); } else { var ctx = this.context; var cd = textureFrame.canvasData; var source = textureFrame.source.image; var matrix = this.camera.matrix; ctx.globalAlpha = this.globalAlpha; ctx.setTransform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); ctx.drawImage(source, cd.x, cd.y, cd.width, cd.height, x, y, cd.width, cd.height); } } , snapshotArea: function (x, y, width, height, callback, type, encoderOptions){ if (this.gl) { this.renderer.snapshotFramebuffer(this.framebuffer, this.width, this.height, callback, false , x, y, width, height, type, encoderOptions); } else { this.renderer.snapshotCanvas(this.canvas, callback, false , x, y, width, height, type, encoderOptions); } return this; } , snapshot: function (callback, type, encoderOptions){ if (this.gl) { this.renderer.snapshotFramebuffer(this.framebuffer, this.width, this.height, callback, false , 0, 0, this.width, this.height, type, encoderOptions); } else { this.renderer.snapshotCanvas(this.canvas, callback, false , 0, 0, this.width, this.height, type, encoderOptions); } return this; } , snapshotPixel: function (x, y, callback){ if (this.gl) { this.renderer.snapshotFramebuffer(this.framebuffer, this.width, this.height, callback, true , x, y); } else { this.renderer.snapshotCanvas(this.canvas, callback, true , x, y); } return this; } , preDestroy: function (){ if (!this._saved) { CanvasPool.remove(this.canvas); if (this.gl) { this.renderer.deleteFramebuffer(this.framebuffer); } this.texture.destroy(); this.camera.destroy(); this.canvas = null ; this.context = null ; this.framebuffer = null ; this.texture = null ; this.glTexture = null ; } } } ); module.exports = RenderTexture;