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 NOOP = require('../../utils/NOOP'); var PIPELINE_CONST = require('../../renderer/webgl/pipelines/const'); var Render = require('./RenderTextureRender'); var RenderTarget = require('../../renderer/webgl/RenderTarget'); 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.renderer; this.textureManager = scene.sys.textures; this.globalTint = 16777215; this.globalAlpha = 1; this.canvas = 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.renderTarget = null ; var renderer = this.renderer; if (!renderer) { this.drawGameObject = NOOP; } else if (renderer.type === CONST.WEBGL) { this.drawGameObject = this.batchGameObjectWebGL; this.renderTarget = new RenderTarget(renderer, width, height, 1, 0, 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(PIPELINE_CONST.SINGLE_PIPELINE); } , setSize: function (width, height){ return this.resize(width, height); } , resize: function (width, height){ if (height === undefined) { height = width; } var frame = this.frame; if (width !== this.width || height !== this.height) { if (frame.name === '__BASE') { this.canvas.width = width; this.canvas.height = height; this.texture.width = width; this.texture.height = height; var renderTarget = this.renderTarget; if (renderTarget) { renderTarget.resize(width, height); frame.glTexture = renderTarget.texture; frame.source.isRenderTexture = true ; frame.source.isGLTexture = true ; frame.source.glTexture = renderTarget.texture; } this.camera.setSize(width, height); frame.source.width = width; frame.source.height = height; frame.setSize(width, height); this.width = width; this.height = height; } } else { var baseFrame = this.texture.getSourceImage(); if (frame.cutX + width > baseFrame.width) { width = baseFrame.width - frame.cutX; } if (frame.cutY + height > baseFrame.height) { height = baseFrame.height - frame.cutY; } frame.setSize(width, height, frame.cutX, frame.cutY); } this.updateDisplayOrigin(); var input = this.input; if (input && !input.customHitArea) { input.hitArea.width = width; input.hitArea.height = height; } 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){ var frame = this.frame; var camera = this.camera; var renderer = this.renderer; if (alpha === undefined) { alpha = 1; } if (x === undefined) { x = 0; } if (y === undefined) { y = 0; } if (width === undefined) { width = frame.cutWidth; } if (height === undefined) { height = frame.cutHeight; } var r = (rgb >> 16 & 255) / 255; var g = (rgb >> 8 & 255) / 255; var b = (rgb & 255) / 255; var renderTarget = this.renderTarget; camera.preRender(); if (renderTarget) { renderTarget.bind(true ); var pipeline = this.pipeline; pipeline.manager.set(pipeline); var tw = renderTarget.width; var th = renderTarget.height; var rw = renderer.width; var rh = renderer.height; var sx = rw / tw; var sy = rh / th; pipeline.drawFillRect(x * sx, y * sy, width * sx, height * sy, Utils.getTintFromFloats(b, g, r, 1), alpha); renderTarget.unbind(true ); } else { var ctx = this.context; renderer.setContext(ctx); ctx.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')'; ctx.fillRect(x + frame.cutX, y + frame.cutY, width, height); renderer.setContext(); } this.dirty = true ; return this; } , clear: function (){ if (this.dirty) { var renderTarget = this.renderTarget; if (renderTarget) { _AN_Call_clear('clear', renderTarget); } 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 ; this.draw(entries, x, y, 1, 16777215); this._eraseMode = false ; return this; } , draw: function (entries, x, y, alpha, tint){ this.beginDraw(); this.batchDraw(entries, x, y, alpha, tint); this.endDraw(); return this; } , drawFrame: function (key, frame, x, y, alpha, tint){ this.beginDraw(); this.batchDrawFrame(key, frame, x, y, alpha, tint); this.endDraw(); return this; } , beginDraw: function (){ var camera = this.camera; var renderer = this.renderer; var renderTarget = this.renderTarget; camera.preRender(); if (renderTarget) { renderer.beginCapture(renderTarget.width, renderTarget.height); } else { renderer.setContext(this.context); } return this; } , batchDraw: 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] ; } this.batchList(entries, x, y, alpha, tint); return this; } , batchDrawFrame: 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 textureFrame = this.textureManager.getFrame(key, frame); if (textureFrame) { if (this.renderTarget) { this.pipeline.batchTextureFrame(textureFrame, x, y, tint, alpha, this.camera.matrix, null ); } else { this.batchTextureFrame(textureFrame, x + this.frame.cutX, y + this.frame.cutY, alpha, tint); } } return this; } , endDraw: function (){ var renderer = this.renderer; var renderTarget = this.renderTarget; if (renderTarget) { var canvasTarget = renderer.endCapture(); var util = renderer.pipelines.setUtility(); util.blitFrame(canvasTarget, renderTarget, 1, false , false , this._eraseMode); renderer.resetScissor(); renderer.resetViewport(); } else { renderer.setContext(); } 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(this.camera)) { 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; gameObject.setPosition(x + this.frame.cutX, y + this.frame.cutY); if (gameObject.renderDirect) { gameObject.renderDirect(this.renderer, gameObject, this.camera); } else { gameObject.renderWebGL(this.renderer, gameObject, this.camera); } 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, 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; var renderTarget = this.renderTarget; if (renderTarget) { 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.save(); ctx.globalCompositeOperation = (this._eraseMode)? 'destination-out': 'source-over'; ctx.globalAlpha = alpha; matrix.setToContext(ctx); ctx.drawImage(source, cd.x, cd.y, cd.width, cd.height, x, y, cd.width, cd.height); ctx.restore(); } } , snapshotArea: function (x, y, width, height, callback, type, encoderOptions){ if (this.renderTarget) { this.renderer.snapshotFramebuffer(this.renderTarget.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.renderTarget) { this.renderer.snapshotFramebuffer(this.renderTarget.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.renderTarget) { this.renderer.snapshotFramebuffer(this.renderTarget.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.renderTarget) { this.renderTarget.destroy(); } this.texture.destroy(); this.camera.destroy(); this.canvas = null ; this.context = null ; this.texture = null ; } } } ); module.exports = RenderTexture;