Skip to content

Instantly share code, notes, and snippets.

@lardratboy
Created August 28, 2014 18:33
Show Gist options
  • Save lardratboy/31666016cf0d98100205 to your computer and use it in GitHub Desktop.
Save lardratboy/31666016cf0d98100205 to your computer and use it in GitHub Desktop.
Phaser group supports visual and input clipping (work in progress)
// Author Brad P. Taylor (bradptaylor+github@gmail.com) license MIT
///<reference path="../../../../bower_components/phaser-official/build/phaser.d.ts"/>
///<reference path="../../DefinitelyTyped/lodash/lodash.d.ts"/>
///<reference path="./prefab.ts"/>
///<reference path="./prefab_extras.ts"/>
module bpt.prefab {
// ------------------------------------------------------------------------
// TODO - think about extending this concept to wrap any method with a signal like this
// also think about splitting out the signal part of this code and use it like a mixin
export class ExtendedGroup extends bpt.prefab.PrefabGroupShim {
// (UPDATE SIGNALS) ---------------------------------------
private onPreUpdateSig:Phaser.Signal;
private onUpdateSig:Phaser.Signal;
private signals:Phaser.Signal[] = [];
createSignal() {
var sig = new Phaser.Signal();
this.signals.push( sig );
return sig;
}
private getUpdateSignal( pre:Boolean ) {
if ( pre ) return this.onPreUpdateSig = this.onPreUpdateSig || this.createSignal();
return this.onUpdateSig = this.onUpdateSig || this.createSignal();
}
addOnceUpdate( pre:Boolean, context:any, fn:any, ...args ) {
return this.getUpdateSignal(pre).addOnce(_.bind( fn, context, args ));
}
addEveryUpdate( pre:Boolean, context:any, fn:any, ...args ) {
return this.getUpdateSignal(pre).add(_.bind( fn, context, args ));
}
preUpdate() {
if ( this.onPreUpdateSig ) { this.onPreUpdateSig.dispatch(this); }
/*
if ( null !== this.clip_mask_ ) {
this.clip_mask_["position"].x = this.parent.position.x + this.position.x;
this.clip_mask_["position"].y = this.parent.position.y + this.position.y;
}
*/
return super.preUpdate();
}
update() {
if ( this.onUpdateSig ) { this.onUpdateSig.dispatch(this); }
return super.update();
}
render() {
}
// (CLIPMASK) ---------------------------------------
private clip_mask_:PIXI.Graphics = null;
private clip_mask_pendingRebuild_:boolean = false;
private clip = new Phaser.Rectangle(0,0,0,0);
get clip_x():number { return this.clip.x; }
set clip_x( n:number ) { if ( n !== this.clip.x ) { this.clip.x = n; this.buildClipMask(); } }
get clip_y():number { return this.clip.y; }
set clip_y( n:number ) { if ( n !== this.clip.y ) { this.clip.y = n; this.buildClipMask(); } }
get clip_width():number { return this.clip.width; }
set clip_width( n:number ) { if ( n !== this.clip.width ) { this.clip.width = n; this.buildClipMask(); } }
get clip_height():number { return this.clip.height; }
set clip_height( n:number ) { if ( n !== this.clip.height ) { this.clip.height = n; this.buildClipMask(); } }
get enableClipMask():boolean {
return !!this.mask;
}
set enableClipMask( enable:boolean ) {
if ( enable ) {
if ( null !== this.clip_mask_ ) {
this.mask = this.clip_mask_;
} else {
this.buildClipMask();
}
} else {
this.mask = null;
}
}
setupClipMask( x, y, width, height, bEnable = true ) {
this.clip_x = Number(x);
this.clip_y = Number(y);
this.clip_width = Number(width);
this.clip_height = Number(height);
this.enableClipMask = bEnable;
}
setClipMaskToBounds( hborder = 0, vborder = hborder, bEnable = true ) {
var bounds = super.getBounds();
this.setupClipMask(
bounds.x+hborder,
bounds.y+vborder,
bounds.width-hborder*2,
bounds.height-vborder*2,
bEnable );
}
renderClipMask() {
if ( null !== this.clip_mask_ ) {
this.clip_mask_.clear();
} else {
this.clip_mask_ = new PIXI.Graphics(null);
this.mask = this.clip_mask_;
}
// -------------------------------------------------------
// HACK.HACK.HACK.HACK.HACK.HACK.HACK.HACK.HACK.HACK.HACK.
// THIS DOES NOT HANDLE TRANSFORMS - SHOULD BE EASY THOUGH
/*
var wm:any = this.worldTransform;
var xx = this.position.x;
var yy = this.position.y;
var xo = wm.a * xx + wm.c * yy + wm.tx;
var yo = wm.d * yy + wm.b * xx + wm.ty;
*/
var xo = 0; //Number(this.position.x);
var yo = 0; //Number(this.position.y);
for ( var p = this.parent; p; p = p.parent ) {
xo += Number(p.position.x);
yo += Number(p.position.y);
}
// HACK.HACK.HACK.HACK.HACK.HACK.HACK.HACK.HACK.HACK.HACK.
// -------------------------------------------------------
this.clip_mask_.beginFill(1,1);
var cx:number = this.clip.x + xo;
var cy:number = this.clip.y + yo;
var cw:number = this.clip.width;
var ch:number = this.clip.height;
this.clip_mask_.drawRect( cx, cy, cw, ch );
this.clip_mask_.endFill();
console.log( cx, cy, cw, ch );
}
private buildClipMask() {
if ( this.clip_mask_pendingRebuild_ ) return;
this.clip_mask_pendingRebuild_ = true;
this.addOnceUpdate( true, this, () => {
this.clip_mask_pendingRebuild_ = false;
this.renderClipMask();
});
}
getBounds(matrix?):any {
if ( !(this.mask || this.clip_mask_pendingRebuild_) ) {
return super.getBounds(matrix);
}
return this.clip;
}
// (INPUT EATER) ---------------------------------------
private static emptyRectangle = new Phaser.Rectangle(0,0,0,0);
private inputEnabled_:boolean = true;
get input_clipping_rect():any {
if ( !this.inputEnabled_) return ExtendedGroup.emptyRectangle;
if ( !(this.mask || this.clip_mask_pendingRebuild_) ) return undefined;
return this.clip;
}
get inputEnabled():boolean {
return this.inputEnabled_;
}
set inputEnabled( enable:boolean ) {
this.inputEnabled_ = enable;
}
// -------------------------------------------------------
releaseReferences() {
this.mask = undefined;
if (this.clip_mask_) {
this.clip_mask_.clear();
this.clip_mask_ = undefined;
}
this.onPreUpdateSig = undefined;
this.onUpdateSig = undefined;
for ( var i in this.signals ) this.signals[i].dispose();
this.signals.length = 0;
}
destroy(destroyChildren?: boolean, soft?: boolean):void {
this.releaseReferences();
super.destroy(destroyChildren, soft);
}
// ---------------------------------------
// THINK - really want a jQuery like selector system for this!
findDecendantsOfType( T:any, depthFirst = false ):any[] {
return bpt.prefab.findDecendantsOfType( this, T, depthFirst );
}
findFirstDecendantOfType( T:any, depthFirst = false ):any {
var found = this.findDecendantsOfType( T, depthFirst );
if ( undefined === found || 0 == found.length ) return;
return found[0];
}
findMatchingDecendantsOfType( re:RegExp, field:string, T:any, depthFirst = false ):any[] {
return bpt.prefab.findMatchingDecendantsOfType( this, re, field, T, depthFirst );
}
findFirstMatchingDecendantOfType( re:RegExp, field:string, T:any, depthFirst = false ):any {
var found = this.findMatchingDecendantsOfType( re, field, T, depthFirst );
if ( undefined === found || 0 == found.length ) return;
return found[0];
}
}
bpt.prefab.Factory.addSimple( 'bpt.ExtendedGroup', ExtendedGroup,
bpt.prefab.Factory.getNamedArgsFor_( 'Phaser.Group' ),
bpt.prefab.Factory.getNamedArgsToStructureFor_( 'Phaser.Group') );
Factory.addAlias( 'ExtendedGroup', 'bpt.ExtendedGroup' );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment