Last active
October 4, 2017 09:52
-
-
Save PrimaryFeather/34967c59f68ebd629cb755a7c3e8984d to your computer and use it in GitHub Desktop.
New Version of "PixelMaskDisplayObject" that works with Starling 2.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package starling.extensions.pixelmask | |
{ | |
import flash.display3D.Context3DBlendFactor; | |
import starling.core.Starling; | |
import starling.display.BlendMode; | |
import starling.display.DisplayObject; | |
import starling.display.DisplayObjectContainer; | |
import starling.display.Image; | |
import starling.events.Event; | |
import starling.rendering.Painter; | |
import starling.textures.RenderTexture; | |
public class PixelMaskDisplayObject extends DisplayObjectContainer | |
{ | |
private static const MASK_MODE_NORMAL:String = "mask"; | |
private static const MASK_MODE_INVERTED:String = "maskinverted"; | |
private var _mask:DisplayObject; | |
private var _renderTexture:RenderTexture; | |
private var _maskRenderTexture:RenderTexture; | |
private var _image:Image; | |
private var _maskImage:Image; | |
private var _superRenderFlag:Boolean = false; | |
private var _inverted:Boolean = false; | |
private var _scaleFactor:Number; | |
private var _isAnimated:Boolean = true; | |
private var _maskRendered:Boolean = false; | |
public function PixelMaskDisplayObject(scaleFactor:Number=-1, isAnimated:Boolean=true) | |
{ | |
super(); | |
_isAnimated = isAnimated; | |
_scaleFactor = scaleFactor; | |
BlendMode.register(MASK_MODE_NORMAL, Context3DBlendFactor.ZERO, Context3DBlendFactor.SOURCE_ALPHA); | |
BlendMode.register(MASK_MODE_INVERTED, Context3DBlendFactor.ZERO, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA); | |
// Handle lost context. By using the conventional event, we can make a weak listener. | |
// This avoids memory leaks when people forget to call "dispose" on the object. | |
Starling.current.stage3D.addEventListener(Event.CONTEXT3D_CREATE, | |
onContextCreated, false, 0, true); | |
} | |
public function get isAnimated():Boolean | |
{ | |
return _isAnimated; | |
} | |
public function set isAnimated(value:Boolean):void | |
{ | |
_isAnimated = value; | |
} | |
override public function dispose():void | |
{ | |
clearRenderTextures(); | |
Starling.current.stage3D.removeEventListener(Event.CONTEXT3D_CREATE, onContextCreated); | |
super.dispose(); | |
} | |
private function onContextCreated(event:Object):void | |
{ | |
refreshRenderTextures(); | |
} | |
public function get inverted():Boolean { return _inverted; } | |
public function set inverted(value:Boolean):void | |
{ | |
_inverted = value; | |
refreshRenderTextures(null); | |
} | |
public function get pixelMask():DisplayObject { return _mask; } | |
public function set pixelMask(value:DisplayObject):void | |
{ | |
_mask = value; | |
if (value) | |
{ | |
if (_mask.width == 0 || _mask.height == 0) | |
throw new Error ("Mask must have dimensions. Current dimensions are " + | |
_mask.width + "x" + _mask.height + "."); | |
refreshRenderTextures(null); | |
} | |
else | |
{ | |
clearRenderTextures(); | |
} | |
} | |
private function clearRenderTextures() : void | |
{ | |
if (_maskRenderTexture) _maskRenderTexture.dispose(); | |
if (_renderTexture) _renderTexture.dispose(); | |
if (_image) _image.dispose(); | |
if (_maskImage) _maskImage.dispose(); | |
} | |
private function refreshRenderTextures(e:Event=null):void | |
{ | |
if (_mask) | |
{ | |
clearRenderTextures(); | |
_maskRenderTexture = new RenderTexture(_mask.width, _mask.height, false, _scaleFactor); | |
_renderTexture = new RenderTexture(_mask.width, _mask.height, false, _scaleFactor); | |
// create image with the new render texture | |
_image = new Image(_renderTexture); | |
// create image to blit the mask onto | |
_maskImage = new Image(_maskRenderTexture); | |
// set the blending mode to MASK (ZERO, SRC_ALPHA) | |
if (_inverted) | |
_maskImage.blendMode = MASK_MODE_INVERTED; | |
else | |
_maskImage.blendMode = MASK_MODE_NORMAL; | |
} | |
_maskRendered = false; | |
} | |
public override function render(painter:Painter):void | |
{ | |
if (_isAnimated || (!_isAnimated && !_maskRendered)) | |
{ | |
painter.finishMeshBatch(); | |
painter.excludeFromCache(this); | |
if (_superRenderFlag || !_mask) | |
{ | |
super.render(painter); | |
} | |
else | |
{ | |
if (_mask) | |
{ | |
_maskRenderTexture.draw(_mask); | |
_renderTexture.drawBundled(drawRenderTextures); | |
_image.render(painter); | |
_maskRendered = true; | |
} | |
} | |
} | |
else | |
{ | |
_image.render(painter); | |
} | |
} | |
private function drawRenderTextures():void | |
{ | |
var a:Number = this.transformationMatrix.a; | |
var b:Number = this.transformationMatrix.b; | |
var c:Number = this.transformationMatrix.c; | |
var d:Number = this.transformationMatrix.d; | |
var tx:Number = this.transformationMatrix.tx; | |
var ty:Number = this.transformationMatrix.ty; | |
this.transformationMatrix.a = 1; | |
this.transformationMatrix.b = 0; | |
this.transformationMatrix.c = 0; | |
this.transformationMatrix.d = 1; | |
this.transformationMatrix.tx = 0; | |
this.transformationMatrix.ty = 0; | |
_superRenderFlag = true; | |
_renderTexture.draw(this); | |
_superRenderFlag = false; | |
this.transformationMatrix.a = a; | |
this.transformationMatrix.b = b; | |
this.transformationMatrix.c = c; | |
this.transformationMatrix.d = d; | |
this.transformationMatrix.tx = tx; | |
this.transformationMatrix.ty = ty; | |
_renderTexture.draw(_maskImage); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment