API Documentation for: 0.2.8
Show:

File:DisplayObject.js

/**
 * @module Pixi Flash
 * @namespace pixiflash
 */
(function(undefined)
{
	var Point = PIXI.Point;
	var ColorFilter = pixiflash.ColorFilter;
	var uniqueId = 0;
	
	/**
	*  Mixins for the display objects used for bridging CreateJS over to PIXI.
	*  @class DisplayObject
	*/
	var DisplayObject = function()
	{
		this.id = ++uniqueId;
		
		//mark these objects so that we can recognize them internally.
		this._isPixiFlash = true;
		/**
		 * x and y skew of the display object, with values in radians.
		 * @property {PIXI.Point} skew
		 */
		this.skew = new Point();
		
		/**
		 * Rotation of the display object, with values in radians.
		 * @property {Number} rotation
		 */
		this._rotation = 0;
		
		this._srB = 0;
		this._srC = 0;
		this._crA = 1;
		this._crD = 1;
		
		this._cachedRotY = 0;
		this._cachedRotX = 0;
		
		/**
		 * If false, the tick will not run on this display object (or its children). This can provide some performance benefits.
		 * In addition to preventing the "tick" event from being dispatched, it will also prevent tick related updates
		 * on some display objects (ex. Sprite & MovieClip frame advancing, DOMElement visibility handling).
		 * @property tickEnabled
		 * @type Boolean
		 * @default true
		 **/
		this.tickEnabled = true;
		
		//remove all listeners on this instance, because the CreateJS published files from flash
		//makes prototypes in a way that breaks normal PIXI listener usage.
		this.removeAllListeners();

		// Bound functions need to be bound later
		this.boundMaskChanged = false;

		//initialize tint variables:
		this._lastComputedTint = this._lastSelfTint = this._lastParentTint = this._selfTint = 0xFFFFFF;
		this.__filters = null;
	};

	var p = DisplayObject.prototype;
	
	var DEG_TO_RAD = Math.PI / 180;
	var RAD_TO_DEG = 180 / Math.PI;
	var PI_2 = Math.PI * 2;
	
	Object.defineProperties(p,
	{
		/**
		 * Private array of filters - for interpretation of CJS ColorFilters as PIXI tint
		 * @property {Array} _filters
		 */
		_filters:
		{
			enumerable: true,
			get: function() { return this.__filters; },
			set: function(value)
			{
				if(value.length == 1 && value[0] instanceof ColorFilter)
				{
					//ColorFilter added by CJS exporter - convert to PIXI tint
					this.tint = value[0].tint;
					this.__filters = null;
				}
				else
				{
					this.__filters = value;
				}
			}
		},
		/**
		 * Tint to apply to this display object - Interpreted from CJS ColorFilter (multiplicative only)
		 * @property {UInt} tint
		 */
		tint:
		{
			enumerable: true,
			get: function() {
				if(this.parent && this.parent._isPixiFlash)
				{
					var selfTint = this._selfTint;
					var parentTint = this.parent.tint;

					if(selfTint == 0xFFFFFF)
						this._lastComputedTint = parentTint;
					else if(parentTint == 0xFFFFFF)
						this._lastComputedTint = selfTint;
					if(this._selfTint != this._lastSelfTint || this.parent.tint != this._lastParentTint)
					{
						//calculate tint first time
						var max = 255;
						var parentR = (parentTint >> 16) & 0xff;
						var parentG = (parentTint >> 8) & 0xff;
						var parentB = parentTint & 0xff;
						var selfR = (selfTint >> 16) & 0xff;
						var selfG = (selfTint >> 8) & 0xff;
						var selfB = selfTint & 0xff;

						this._lastComputedTint = (Math.round((parentR * selfR) / max) << 16) | (Math.round((parentG * selfG) / max) << 8) | Math.round((parentB * selfB) / max);
					}

					this._lastSelfTint = selfTint;
					this._lastParentTint = parentTint;

					return this._lastComputedTint;
				}
				else
				{
					return this._selfTint;
				}
			},
			set: function(value)
			{
				this._selfTint = value;
			}
		},
		/**
		 * The x skew value of the display object, in degrees.
		 * This property provides parity with CreateJS display objects.
		 * @property {Number} skewX
		 */
		skewX:
		{
			enumerable: true,
			get: function() { return this.skew.x * RAD_TO_DEG; },
			set: function(value)
			{
				this.skew.x = value * DEG_TO_RAD;
			}
		},
		/**
		 * The y skew value of the display object, in degrees.
		 * This property provides parity with CreateJS display objects.
		 * @property {Number} skewY
		 */
		skewY:
		{
			enumerable: true,
			get: function() { return this.skew.y * RAD_TO_DEG; },
			set: function(value)
			{
				this.skew.y = value * DEG_TO_RAD;
			}
		},
		/**
		 * The rotation of the display object, in degrees.
		 * This overrides the radian degrees of the PIXI display objects so that
		 * tweening exported from Flash will work correctly.
		 * @property {Number} rotation
		 */
		rotation:
		{
			enumerable: true,
			get: function() { return this._rotation * RAD_TO_DEG; },
			set: function(value)
			{
				this._rotation = value * DEG_TO_RAD;
			}
		},
		/**
		 * The x scale value of the display object.
		 * This property provides parity with CreateJS display objects.
		 * @property {Number} scaleX
		 */
		scaleX:
		{
			enumerable: true,
			get: function() { return this.scale.x; },
			set: function(value)
			{
				this.scale.x = value;
			}
		},
		/**
		 * The y scale value of the display object.
		 * This property provides parity with CreateJS display objects.
		 * @property {Number} scaleY
		 */
		scaleY:
		{
			enumerable: true,
			get: function() { return this.scale.y; },
			set: function(value)
			{
				this.scale.y = value;
			}
		},
		/**
		 * The x value of the registration, or pivot, point.
		 * This property provides parity with CreateJS display objects.
		 * @property {Number} regX
		 */
		regX:
		{
			enumerable: true,
			get: function() { return this.pivot.x; },
			set: function(value)
			{
				this.pivot.x = value;
			}
		},
		/**
		 * The y value of the registration, or pivot, point.
		 * This property provides parity with CreateJS display objects.
		 * @property {Number} regY
		 */
		regY:
		{
			enumerable: true,
			get: function() { return this.pivot.y; },
			set: function(value)
			{
				this.pivot.y = value;
			}
		},

		/**
		 * The drawing graphics, these are necessary
		 * for the compability with EaselJS Flash exports.
		 * @property {pixiflash.Shape|pixiflash.Sprite} mask
		 */
		mask: {
			enumerable: true,
			get: function()
			{
				return this._mask;
			},
			set: function (mask)
			{
				if (this._mask)
				{
					// Remove the old mask if we're a shape
					if (this._mask.__parentShape)
					{
						var parentShape = this._mask.__parentShape;
						if (parentShape.parent)
							parentShape.parent.removeChild(parentShape);
						parentShape.off('graphicsChanged', this.onShapeChanged);
						delete this._mask.__parentShape;
					}
					this._mask.renderable = true;
				}
				// If the mask is a shape apply the graphics as the shape
				if (mask && mask instanceof pixiflash.Shape)
				{
					this._mask = mask.graphics;
					this._mask.__parentShape = mask;
					if(!this.boundMaskChanged)
					{
						this.boundMaskChanged = true;
						this.onShapeChanged = this.onShapeChanged.bind(this);
					}
					mask.once('graphicsChanged', this.onShapeChanged);
				}
				else
				{
					this._mask = mask;
				}
				if (this._mask)
				{
					// Wait until we're add and then add the mask
					// on the same container as this display object
					if (!this.parent)
					{
						this.once("added", function()
						{
							if(!this._mask) return;
							this.parent.addChild(this._mask.__parentShape || this._mask);
						});
					}
					else
					{
						this.parent.addChild(this._mask.__parentShape || this._mask);
					}
					this._mask.renderable = false;
				}
			}
		}
	});

	
	/**
	 * Dummy function for CJS export compatibility
	 * @method cache
	 */
	p.cache = function()
	{
		//don't do anything!
	};

	/**
	 * Graphics object was updated on the shape dynamically, update the mask
	 * @method onShapeChanged
	 * @private
	 * @param {pixiflash.Shape} shape
	 */
	p.onShapeChanged = function(shape)
	{
		// reset the shape mask
		this.mask = shape;
	};
	
	p.displayObjectUpdateTransform = function()
	{
		// create some matrix refs for easy access
		var pt = this.parent.worldTransform;
		var wt = this.worldTransform;

		// temporary matrix variables
		var a, b, c, d, tx, ty,
			rotY = this._rotation + this.skew.y,
			rotX = this._rotation + this.skew.x;

		// so if rotation is between 0 then we can simplify the multiplication process...
		if (rotY % PI_2 || rotX % PI_2)
		{
			// check to see if the rotation is the same as the previous render. This means we only need to use sin and cos when rotation actually changes
			if (rotX !== this._cachedRotX || rotY !== this._cachedRotY)
			{
				// cache new values
				this._cachedRotX = rotX;
				this._cachedRotY = rotY;
				
				// recalculate expensive ops
				this._crA = Math.cos(rotY);
				this._srB = Math.sin(rotY);
				
				this._srC = Math.sin(-rotX);
				this._crD = Math.cos(rotX);
			}

			// get the matrix values of the displayobject based on its transform properties..
			a  = this._crA * this.scale.x;
			b  = this._srB * this.scale.x;
			c  = this._srC * this.scale.y;
			d  = this._crD * this.scale.y;
			tx =  this.position.x;
			ty =  this.position.y;

			// check for pivot.. not often used so geared towards that fact!
			if (this.pivot.x || this.pivot.y)
			{
				tx -= this.pivot.x * a + this.pivot.y * c;
				ty -= this.pivot.x * b + this.pivot.y * d;
			}

			// concat the parent matrix with the objects transform.
			wt.a  = a  * pt.a + b  * pt.c;
			wt.b  = a  * pt.b + b  * pt.d;
			wt.c  = c  * pt.a + d  * pt.c;
			wt.d  = c  * pt.b + d  * pt.d;
			wt.tx = tx * pt.a + ty * pt.c + pt.tx;
			wt.ty = tx * pt.b + ty * pt.d + pt.ty;
		}
		else
		{
			// lets do the fast version as we know there is no rotation..
			a  = this.scale.x;
			d  = this.scale.y;

			tx = this.position.x - this.pivot.x * a;
			ty = this.position.y - this.pivot.y * d;

			wt.a  = a  * pt.a;
			wt.b  = a  * pt.b;
			wt.c  = d  * pt.c;
			wt.d  = d  * pt.d;
			wt.tx = tx * pt.a + ty * pt.c + pt.tx;
			wt.ty = tx * pt.b + ty * pt.d + pt.ty;
		}

		// multiply the alphas..
		this.worldAlpha = this.alpha * this.parent.worldAlpha;

		// reset the bounds each time this is called!
		this._currentBounds = null;
	};
	
	p.setTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY)
	{
		this.position.x = x || 0;
		this.position.y = y || 0;
		this.scale.x = !scaleX ? 1 : scaleX;
		this.scale.y = !scaleY ? 1 : scaleY;
		this.rotation = rotation || 0;
		this.skewX = skewX || 0;
		this.skewY = skewY || 0;
		this.pivot.x = regX || 0;
		this.pivot.y = regY || 0;
		return this;
	};
	
	DisplayObject.mixin = function(targetPrototype)
	{
		for(var prop in p)
		{
			// For things that we set using Object.defineProperty
			// very important that enumerable:true for the
			// defineProperty options
			var propDesc = Object.getOwnPropertyDescriptor(p, prop);
			if(propDesc)
			{
				Object.defineProperty(targetPrototype, prop, propDesc);
			}
			else
			{
				// Should cover all other prototype methods/properties
				targetPrototype[prop] = p[prop];
			}
		}
	};
	
	pixiflash.DisplayObject = DisplayObject;
	
}());