updated pixi to v2

This commit is contained in:
logsol 2014-12-21 19:32:18 +01:00
parent a5b3d2f671
commit 58b83f7297
95 changed files with 44677 additions and 3522 deletions

View file

@ -0,0 +1,310 @@
/* Esoteric Software SPINE wrapper for pixi.js */
spine.Bone.yDown = true;
PIXI.AnimCache = {};
/**
* Supporting class to load images from spine atlases as per spine spec.
*
* @class SpineTextureLoader
* @uses EventTarget
* @constructor
* @param basePath {String} Tha base path where to look for the images to be loaded
* @param crossorigin {Boolean} Whether requests should be treated as crossorigin
*/
PIXI.SpineTextureLoader = function(basePath, crossorigin)
{
PIXI.EventTarget.call(this);
this.basePath = basePath;
this.crossorigin = crossorigin;
this.loadingCount = 0;
};
/* constructor */
PIXI.SpineTextureLoader.prototype = PIXI.SpineTextureLoader;
/**
* Starts loading a base texture as per spine specification
*
* @method load
* @param page {spine.AtlasPage} Atlas page to which texture belongs
* @param file {String} The file to load, this is just the file path relative to the base path configured in the constructor
*/
PIXI.SpineTextureLoader.prototype.load = function(page, file)
{
page.rendererObject = PIXI.BaseTexture.fromImage(this.basePath + '/' + file, this.crossorigin);
if (!page.rendererObject.hasLoaded)
{
var scope = this;
++scope.loadingCount;
page.rendererObject.addEventListener('loaded', function(){
--scope.loadingCount;
scope.dispatchEvent({
type: 'loadedBaseTexture',
content: scope
});
});
}
};
/**
* Unloads a previously loaded texture as per spine specification
*
* @method unload
* @param texture {BaseTexture} Texture object to destroy
*/
PIXI.SpineTextureLoader.prototype.unload = function(texture)
{
texture.destroy(true);
};
/**
* A class that enables the you to import and run your spine animations in pixi.
* Spine animation data needs to be loaded using the PIXI.AssetLoader or PIXI.SpineLoader before it can be used by this class
* See example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source
*
* @class Spine
* @extends DisplayObjectContainer
* @constructor
* @param url {String} The url of the spine anim file to be used
*/
PIXI.Spine = function (url) {
PIXI.DisplayObjectContainer.call(this);
this.spineData = PIXI.AnimCache[url];
if (!this.spineData) {
throw new Error('Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: ' + url);
}
this.skeleton = new spine.Skeleton(this.spineData);
this.skeleton.updateWorldTransform();
this.stateData = new spine.AnimationStateData(this.spineData);
this.state = new spine.AnimationState(this.stateData);
this.slotContainers = [];
for (var i = 0, n = this.skeleton.drawOrder.length; i < n; i++) {
var slot = this.skeleton.drawOrder[i];
var attachment = slot.attachment;
var slotContainer = new PIXI.DisplayObjectContainer();
this.slotContainers.push(slotContainer);
this.addChild(slotContainer);
if (attachment instanceof spine.RegionAttachment)
{
var spriteName = attachment.rendererObject.name;
var sprite = this.createSprite(slot, attachment);
slot.currentSprite = sprite;
slot.currentSpriteName = spriteName;
slotContainer.addChild(sprite);
}
else if (attachment instanceof spine.MeshAttachment)
{
var mesh = this.createMesh(slot, attachment);
slot.currentMesh = mesh;
slot.currentMeshName = attachment.name;
slotContainer.addChild(mesh);
}
else
{
continue;
}
}
this.autoUpdate = true;
};
PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
PIXI.Spine.prototype.constructor = PIXI.Spine;
/**
* If this flag is set to true, the spine animation will be autoupdated every time
* the object id drawn. The down side of this approach is that the delta time is
* automatically calculated and you could miss out on cool effects like slow motion,
* pause, skip ahead and the sorts. Most of these effects can be achieved even with
* autoupdate enabled but are harder to achieve.
*
* @property autoUpdate
* @type { Boolean }
* @default true
*/
Object.defineProperty(PIXI.Spine.prototype, 'autoUpdate', {
get: function()
{
return (this.updateTransform === PIXI.Spine.prototype.autoUpdateTransform);
},
set: function(value)
{
this.updateTransform = value ? PIXI.Spine.prototype.autoUpdateTransform : PIXI.DisplayObjectContainer.prototype.updateTransform;
}
});
/**
* Update the spine skeleton and its animations by delta time (dt)
*
* @method update
* @param dt {Number} Delta time. Time by which the animation should be updated
*/
PIXI.Spine.prototype.update = function(dt)
{
this.state.update(dt);
this.state.apply(this.skeleton);
this.skeleton.updateWorldTransform();
var drawOrder = this.skeleton.drawOrder;
for (var i = 0, n = drawOrder.length; i < n; i++) {
var slot = drawOrder[i];
var attachment = slot.attachment;
var slotContainer = this.slotContainers[i];
if (!attachment)
{
slotContainer.visible = false;
continue;
}
var type = attachment.type;
if (type === spine.AttachmentType.region)
{
if (attachment.rendererObject)
{
if (!slot.currentSpriteName || slot.currentSpriteName !== attachment.name)
{
var spriteName = attachment.rendererObject.name;
if (slot.currentSprite !== undefined)
{
slot.currentSprite.visible = false;
}
slot.sprites = slot.sprites || {};
if (slot.sprites[spriteName] !== undefined)
{
slot.sprites[spriteName].visible = true;
}
else
{
var sprite = this.createSprite(slot, attachment);
slotContainer.addChild(sprite);
}
slot.currentSprite = slot.sprites[spriteName];
slot.currentSpriteName = spriteName;
}
}
var bone = slot.bone;
slotContainer.position.x = bone.worldX + attachment.x * bone.m00 + attachment.y * bone.m01;
slotContainer.position.y = bone.worldY + attachment.x * bone.m10 + attachment.y * bone.m11;
slotContainer.scale.x = bone.worldScaleX;
slotContainer.scale.y = bone.worldScaleY;
slotContainer.rotation = -(slot.bone.worldRotation * spine.degRad);
slot.currentSprite.tint = PIXI.rgb2hex([slot.r,slot.g,slot.b]);
}
else if (type === spine.AttachmentType.skinnedmesh)
{
if (!slot.currentMeshName || slot.currentMeshName !== attachment.name)
{
var meshName = attachment.name;
if (slot.currentMesh !== undefined)
{
slot.currentMesh.visible = false;
}
slot.meshes = slot.meshes || {};
if (slot.meshes[meshName] !== undefined)
{
slot.meshes[meshName].visible = true;
}
else
{
var mesh = this.createMesh(slot, attachment);
slotContainer.addChild(mesh);
}
slot.currentMesh = slot.meshes[meshName];
slot.currentMeshName = meshName;
}
attachment.computeWorldVertices(slot.bone.skeleton.x, slot.bone.skeleton.y, slot, slot.currentMesh.vertices);
}
else
{
slotContainer.visible = false;
continue;
}
slotContainer.visible = true;
slotContainer.alpha = slot.a;
}
};
/**
* When autoupdate is set to yes this function is used as pixi's updateTransform function
*
* @method autoUpdateTransform
* @private
*/
PIXI.Spine.prototype.autoUpdateTransform = function () {
this.lastTime = this.lastTime || Date.now();
var timeDelta = (Date.now() - this.lastTime) * 0.001;
this.lastTime = Date.now();
this.update(timeDelta);
PIXI.DisplayObjectContainer.prototype.updateTransform.call(this);
};
/**
* Create a new sprite to be used with spine.RegionAttachment
*
* @method createSprite
* @param slot {spine.Slot} The slot to which the attachment is parented
* @param attachment {spine.RegionAttachment} The attachment that the sprite will represent
* @private
*/
PIXI.Spine.prototype.createSprite = function (slot, attachment) {
var descriptor = attachment.rendererObject;
var baseTexture = descriptor.page.rendererObject;
var spriteRect = new PIXI.Rectangle(descriptor.x,
descriptor.y,
descriptor.rotate ? descriptor.height : descriptor.width,
descriptor.rotate ? descriptor.width : descriptor.height);
var spriteTexture = new PIXI.Texture(baseTexture, spriteRect);
var sprite = new PIXI.Sprite(spriteTexture);
var baseRotation = descriptor.rotate ? Math.PI * 0.5 : 0.0;
sprite.scale.set(descriptor.width / descriptor.originalWidth, descriptor.height / descriptor.originalHeight);
sprite.rotation = baseRotation - (attachment.rotation * spine.degRad);
sprite.anchor.x = sprite.anchor.y = 0.5;
slot.sprites = slot.sprites || {};
slot.sprites[descriptor.name] = sprite;
return sprite;
};
PIXI.Spine.prototype.createMesh = function (slot, attachment) {
var descriptor = attachment.rendererObject;
var baseTexture = descriptor.page.rendererObject;
var texture = new PIXI.Texture(baseTexture);
var strip = new PIXI.Strip(texture);
strip.drawMode = PIXI.Strip.DrawModes.TRIANGLES;
strip.canvasPadding = 1.5;
strip.vertices = new PIXI.Float32Array(attachment.uvs.length);
strip.uvs = attachment.uvs;
strip.indices = attachment.triangles;
slot.meshes = slot.meshes || {};
slot.meshes[attachment.name] = strip;
return strip;
};

174
app/Lib/Vendor/src/pixi/extras/Rope.js vendored Normal file
View file

@ -0,0 +1,174 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
* @copyright Mat Groves, Rovanion Luckey
*/
/**
*
* @class Rope
* @constructor
* @extends Strip
* @param {Texture} texture - The texture to use on the rope.
* @param {Array} points - An array of {PIXI.Point}.
*
*/
PIXI.Rope = function(texture, points)
{
PIXI.Strip.call( this, texture );
this.points = points;
this.vertices = new PIXI.Float32Array(points.length * 4);
this.uvs = new PIXI.Float32Array(points.length * 4);
this.colors = new PIXI.Float32Array(points.length * 2);
this.indices = new PIXI.Uint16Array(points.length * 2);
this.refresh();
};
// constructor
PIXI.Rope.prototype = Object.create( PIXI.Strip.prototype );
PIXI.Rope.prototype.constructor = PIXI.Rope;
/*
* Refreshes
*
* @method refresh
*/
PIXI.Rope.prototype.refresh = function()
{
var points = this.points;
if(points.length < 1) return;
var uvs = this.uvs;
var lastPoint = points[0];
var indices = this.indices;
var colors = this.colors;
this.count-=0.2;
uvs[0] = 0;
uvs[1] = 0;
uvs[2] = 0;
uvs[3] = 1;
colors[0] = 1;
colors[1] = 1;
indices[0] = 0;
indices[1] = 1;
var total = points.length,
point, index, amount;
for (var i = 1; i < total; i++)
{
point = points[i];
index = i * 4;
// time to do some smart drawing!
amount = i / (total-1);
if(i%2)
{
uvs[index] = amount;
uvs[index+1] = 0;
uvs[index+2] = amount;
uvs[index+3] = 1;
}
else
{
uvs[index] = amount;
uvs[index+1] = 0;
uvs[index+2] = amount;
uvs[index+3] = 1;
}
index = i * 2;
colors[index] = 1;
colors[index+1] = 1;
index = i * 2;
indices[index] = index;
indices[index + 1] = index + 1;
lastPoint = point;
}
};
/*
* Updates the object transform for rendering
*
* @method updateTransform
* @private
*/
PIXI.Rope.prototype.updateTransform = function()
{
var points = this.points;
if(points.length < 1)return;
var lastPoint = points[0];
var nextPoint;
var perp = {x:0, y:0};
this.count-=0.2;
var vertices = this.vertices;
var total = points.length,
point, index, ratio, perpLength, num;
for (var i = 0; i < total; i++)
{
point = points[i];
index = i * 4;
if(i < points.length-1)
{
nextPoint = points[i+1];
}
else
{
nextPoint = point;
}
perp.y = -(nextPoint.x - lastPoint.x);
perp.x = nextPoint.y - lastPoint.y;
ratio = (1 - (i / (total-1))) * 10;
if(ratio > 1) ratio = 1;
perpLength = Math.sqrt(perp.x * perp.x + perp.y * perp.y);
num = this.texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio;
perp.x /= perpLength;
perp.y /= perpLength;
perp.x *= num;
perp.y *= num;
vertices[index] = point.x + perp.x;
vertices[index+1] = point.y + perp.y;
vertices[index+2] = point.x - perp.x;
vertices[index+3] = point.y - perp.y;
lastPoint = point;
}
PIXI.DisplayObjectContainer.prototype.updateTransform.call( this );
};
/*
* Sets the texture that the Rope will use
*
* @method setTexture
* @param texture {Texture} the texture that will be used
*/
PIXI.Rope.prototype.setTexture = function(texture)
{
// stop current texture
this.texture = texture;
//this.updateFrame = true;
};

27
app/Lib/Vendor/src/pixi/extras/SPINE-LICENSE vendored Executable file
View file

@ -0,0 +1,27 @@
Spine Runtimes Software License
Version 2.1
Copyright (c) 2013, Esoteric Software
All rights reserved.
You are granted a perpetual, non-exclusive, non-sublicensable and
non-transferable license to install, execute and perform the Spine Runtimes
Software (the "Software") solely for internal use. Without the written
permission of Esoteric Software (typically granted by licensing Spine), you
may not (a) modify, translate, adapt or otherwise create derivative works,
improvements of the Software or develop new applications using the Software
or (b) remove, delete, alter or obscure any trademarks or any copyright,
trademark, patent or other intellectual property or proprietary rights notices
on or in the Software, including any copy thereof. Redistributions in binary
or source form must include this license and terms.
THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

2626
app/Lib/Vendor/src/pixi/extras/Spine.js vendored Normal file

File diff suppressed because it is too large Load diff

469
app/Lib/Vendor/src/pixi/extras/Strip.js vendored Normal file
View file

@ -0,0 +1,469 @@
/**
* @author Mat Groves http://matgroves.com/
*/
/**
*
* @class Strip
* @extends DisplayObjectContainer
* @constructor
* @param texture {Texture} The texture to use
* @param width {Number} the width
* @param height {Number} the height
*
*/
PIXI.Strip = function(texture)
{
PIXI.DisplayObjectContainer.call( this );
/**
* The texture of the strip
*
* @property texture
* @type Texture
*/
this.texture = texture;
// set up the main bits..
this.uvs = new PIXI.Float32Array([0, 1,
1, 1,
1, 0,
0, 1]);
this.vertices = new PIXI.Float32Array([0, 0,
100, 0,
100, 100,
0, 100]);
this.colors = new PIXI.Float32Array([1, 1, 1, 1]);
this.indices = new PIXI.Uint16Array([0, 1, 2, 3]);
/**
* Whether the strip is dirty or not
*
* @property dirty
* @type Boolean
*/
this.dirty = true;
/**
* The blend mode to be applied to the sprite. Set to PIXI.blendModes.NORMAL to remove any blend mode.
*
* @property blendMode
* @type Number
* @default PIXI.blendModes.NORMAL;
*/
this.blendMode = PIXI.blendModes.NORMAL;
/**
* Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other.
*
* @property canvasPadding
* @type Number
*/
this.canvasPadding = 0;
this.drawMode = PIXI.Strip.DrawModes.TRIANGLE_STRIP;
};
// constructor
PIXI.Strip.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
PIXI.Strip.prototype.constructor = PIXI.Strip;
PIXI.Strip.prototype._renderWebGL = function(renderSession)
{
// if the sprite is not visible or the alpha is 0 then no need to render this element
if(!this.visible || this.alpha <= 0)return;
// render triangle strip..
renderSession.spriteBatch.stop();
// init! init!
if(!this._vertexBuffer)this._initWebGL(renderSession);
renderSession.shaderManager.setShader(renderSession.shaderManager.stripShader);
this._renderStrip(renderSession);
///renderSession.shaderManager.activateDefaultShader();
renderSession.spriteBatch.start();
//TODO check culling
};
PIXI.Strip.prototype._initWebGL = function(renderSession)
{
// build the strip!
var gl = renderSession.gl;
this._vertexBuffer = gl.createBuffer();
this._indexBuffer = gl.createBuffer();
this._uvBuffer = gl.createBuffer();
this._colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.uvs, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, this._colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.colors, gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
};
PIXI.Strip.prototype._renderStrip = function(renderSession)
{
var gl = renderSession.gl;
var projection = renderSession.projection,
offset = renderSession.offset,
shader = renderSession.shaderManager.stripShader;
var drawMode = this.drawMode === PIXI.Strip.DrawModes.TRIANGLE_STRIP ? gl.TRIANGLE_STRIP : gl.TRIANGLES;
// gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mat4Real);
renderSession.blendModeManager.setBlendMode(this.blendMode);
// set uniforms
gl.uniformMatrix3fv(shader.translationMatrix, false, this.worldTransform.toArray(true));
gl.uniform2f(shader.projectionVector, projection.x, -projection.y);
gl.uniform2f(shader.offsetVector, -offset.x, -offset.y);
gl.uniform1f(shader.alpha, this.worldAlpha);
if(!this.dirty)
{
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices);
gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
// update the uvs
gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
gl.activeTexture(gl.TEXTURE0);
// check if a texture is dirty..
if(this.texture.baseTexture._dirty[gl.id])
{
renderSession.renderer.updateTexture(this.texture.baseTexture);
}
else
{
// bind the current texture
gl.bindTexture(gl.TEXTURE_2D, this.texture.baseTexture._glTextures[gl.id]);
}
// dont need to upload!
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
}
else
{
this.dirty = false;
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
// update the uvs
gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this.uvs, gl.STATIC_DRAW);
gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
gl.activeTexture(gl.TEXTURE0);
// check if a texture is dirty..
if(this.texture.baseTexture._dirty[gl.id])
{
renderSession.renderer.updateTexture(this.texture.baseTexture);
}
else
{
gl.bindTexture(gl.TEXTURE_2D, this.texture.baseTexture._glTextures[gl.id]);
}
// dont need to upload!
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices, gl.STATIC_DRAW);
}
//console.log(gl.TRIANGLE_STRIP)
//
//
gl.drawElements(drawMode, this.indices.length, gl.UNSIGNED_SHORT, 0);
};
PIXI.Strip.prototype._renderCanvas = function(renderSession)
{
var context = renderSession.context;
var transform = this.worldTransform;
if (renderSession.roundPixels)
{
context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0);
}
else
{
context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty);
}
if (this.drawMode === PIXI.Strip.DrawModes.TRIANGLE_STRIP)
{
this._renderCanvasTriangleStrip(context);
}
else
{
this._renderCanvasTriangles(context);
}
};
PIXI.Strip.prototype._renderCanvasTriangleStrip = function(context)
{
// draw triangles!!
var vertices = this.vertices;
var uvs = this.uvs;
var length = vertices.length / 2;
this.count++;
for (var i = 0; i < length - 2; i++) {
// draw some triangles!
var index = i * 2;
this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4));
}
};
PIXI.Strip.prototype._renderCanvasTriangles = function(context)
{
// draw triangles!!
var vertices = this.vertices;
var uvs = this.uvs;
var indices = this.indices;
var length = indices.length;
this.count++;
for (var i = 0; i < length; i += 3) {
// draw some triangles!
var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2;
this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2);
}
};
PIXI.Strip.prototype._renderCanvasDrawTriangle = function(context, vertices, uvs, index0, index1, index2)
{
var textureSource = this.texture.baseTexture.source;
var textureWidth = this.texture.width;
var textureHeight = this.texture.height;
var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2];
var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1];
var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth;
var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight;
if (this.canvasPadding > 0) {
var paddingX = this.canvasPadding / this.worldTransform.a;
var paddingY = this.canvasPadding / this.worldTransform.d;
var centerX = (x0 + x1 + x2) / 3;
var centerY = (y0 + y1 + y2) / 3;
var normX = x0 - centerX;
var normY = y0 - centerY;
var dist = Math.sqrt(normX * normX + normY * normY);
x0 = centerX + (normX / dist) * (dist + paddingX);
y0 = centerY + (normY / dist) * (dist + paddingY);
//
normX = x1 - centerX;
normY = y1 - centerY;
dist = Math.sqrt(normX * normX + normY * normY);
x1 = centerX + (normX / dist) * (dist + paddingX);
y1 = centerY + (normY / dist) * (dist + paddingY);
normX = x2 - centerX;
normY = y2 - centerY;
dist = Math.sqrt(normX * normX + normY * normY);
x2 = centerX + (normX / dist) * (dist + paddingX);
y2 = centerY + (normY / dist) * (dist + paddingY);
}
context.save();
context.beginPath();
context.moveTo(x0, y0);
context.lineTo(x1, y1);
context.lineTo(x2, y2);
context.closePath();
context.clip();
// Compute matrix transform
var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2);
var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2);
var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2);
var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2);
var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2);
var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2);
var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2);
context.transform(deltaA / delta, deltaD / delta,
deltaB / delta, deltaE / delta,
deltaC / delta, deltaF / delta);
context.drawImage(textureSource, 0, 0);
context.restore();
};
/**
* Renders a flat strip
*
* @method renderStripFlat
* @param strip {Strip} The Strip to render
* @private
*/
PIXI.Strip.prototype.renderStripFlat = function(strip)
{
var context = this.context;
var vertices = strip.vertices;
var length = vertices.length/2;
this.count++;
context.beginPath();
for (var i=1; i < length-2; i++)
{
// draw some triangles!
var index = i*2;
var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4];
var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5];
context.moveTo(x0, y0);
context.lineTo(x1, y1);
context.lineTo(x2, y2);
}
context.fillStyle = '#FF0000';
context.fill();
context.closePath();
};
/*
PIXI.Strip.prototype.setTexture = function(texture)
{
//TODO SET THE TEXTURES
//TODO VISIBILITY
// stop current texture
this.texture = texture;
this.width = texture.frame.width;
this.height = texture.frame.height;
this.updateFrame = true;
};
*/
/**
* When the texture is updated, this event will fire to update the scale and frame
*
* @method onTextureUpdate
* @param event
* @private
*/
PIXI.Strip.prototype.onTextureUpdate = function()
{
this.updateFrame = true;
};
/**
* Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account.
*
* @method getBounds
* @param matrix {Matrix} the transformation matrix of the sprite
* @return {Rectangle} the framing rectangle
*/
PIXI.Strip.prototype.getBounds = function(matrix)
{
var worldTransform = matrix || this.worldTransform;
var a = worldTransform.a;
var b = worldTransform.b;
var c = worldTransform.c;
var d = worldTransform.d;
var tx = worldTransform.tx;
var ty = worldTransform.ty;
var maxX = -Infinity;
var maxY = -Infinity;
var minX = Infinity;
var minY = Infinity;
var vertices = this.vertices;
for (var i = 0, n = vertices.length; i < n; i += 2)
{
var rawX = vertices[i], rawY = vertices[i + 1];
var x = (a * rawX) + (c * rawY) + tx;
var y = (d * rawY) + (b * rawX) + ty;
minX = x < minX ? x : minX;
minY = y < minY ? y : minY;
maxX = x > maxX ? x : maxX;
maxY = y > maxY ? y : maxY;
}
if (minX === -Infinity || maxY === Infinity)
{
return PIXI.EmptyRectangle;
}
var bounds = this._bounds;
bounds.x = minX;
bounds.width = maxX - minX;
bounds.y = minY;
bounds.height = maxY - minY;
// store a reference so that if this function gets called again in the render cycle we do not have to recalculate
this._currentBounds = bounds;
return bounds;
};
/**
* Different drawing buffer modes supported
*
* @property
* @type {{TRIANGLE_STRIP: number, TRIANGLES: number}}
* @static
*/
PIXI.Strip.DrawModes = {
TRIANGLE_STRIP: 0,
TRIANGLES: 1
};

View file

@ -0,0 +1,466 @@
/**
* @author Mat Groves http://matgroves.com/
*/
/**
* A tiling sprite is a fast way of rendering a tiling image
*
* @class TilingSprite
* @extends Sprite
* @constructor
* @param texture {Texture} the texture of the tiling sprite
* @param width {Number} the width of the tiling sprite
* @param height {Number} the height of the tiling sprite
*/
PIXI.TilingSprite = function(texture, width, height)
{
PIXI.Sprite.call( this, texture);
/**
* The with of the tiling sprite
*
* @property width
* @type Number
*/
this._width = width || 100;
/**
* The height of the tiling sprite
*
* @property height
* @type Number
*/
this._height = height || 100;
/**
* The scaling of the image that is being tiled
*
* @property tileScale
* @type Point
*/
this.tileScale = new PIXI.Point(1,1);
/**
* A point that represents the scale of the texture object
*
* @property tileScaleOffset
* @type Point
*/
this.tileScaleOffset = new PIXI.Point(1,1);
/**
* The offset position of the image that is being tiled
*
* @property tilePosition
* @type Point
*/
this.tilePosition = new PIXI.Point(0,0);
/**
* Whether this sprite is renderable or not
*
* @property renderable
* @type Boolean
* @default true
*/
this.renderable = true;
/**
* The tint applied to the sprite. This is a hex value
*
* @property tint
* @type Number
* @default 0xFFFFFF
*/
this.tint = 0xFFFFFF;
/**
* The blend mode to be applied to the sprite
*
* @property blendMode
* @type Number
* @default PIXI.blendModes.NORMAL;
*/
this.blendMode = PIXI.blendModes.NORMAL;
};
// constructor
PIXI.TilingSprite.prototype = Object.create(PIXI.Sprite.prototype);
PIXI.TilingSprite.prototype.constructor = PIXI.TilingSprite;
/**
* The width of the sprite, setting this will actually modify the scale to achieve the value set
*
* @property width
* @type Number
*/
Object.defineProperty(PIXI.TilingSprite.prototype, 'width', {
get: function() {
return this._width;
},
set: function(value) {
this._width = value;
}
});
/**
* The height of the TilingSprite, setting this will actually modify the scale to achieve the value set
*
* @property height
* @type Number
*/
Object.defineProperty(PIXI.TilingSprite.prototype, 'height', {
get: function() {
return this._height;
},
set: function(value) {
this._height = value;
}
});
PIXI.TilingSprite.prototype.setTexture = function(texture)
{
if (this.texture === texture) return;
this.texture = texture;
this.refreshTexture = true;
this.cachedTint = 0xFFFFFF;
};
/**
* Renders the object using the WebGL renderer
*
* @method _renderWebGL
* @param renderSession {RenderSession}
* @private
*/
PIXI.TilingSprite.prototype._renderWebGL = function(renderSession)
{
if (this.visible === false || this.alpha === 0) return;
var i,j;
if (this._mask)
{
renderSession.spriteBatch.stop();
renderSession.maskManager.pushMask(this.mask, renderSession);
renderSession.spriteBatch.start();
}
if (this._filters)
{
renderSession.spriteBatch.flush();
renderSession.filterManager.pushFilter(this._filterBlock);
}
if (!this.tilingTexture || this.refreshTexture)
{
this.generateTilingTexture(true);
if (this.tilingTexture && this.tilingTexture.needsUpdate)
{
//TODO - tweaking
PIXI.updateWebGLTexture(this.tilingTexture.baseTexture, renderSession.gl);
this.tilingTexture.needsUpdate = false;
// this.tilingTexture._uvs = null;
}
}
else
{
renderSession.spriteBatch.renderTilingSprite(this);
}
// simple render children!
for (i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderWebGL(renderSession);
}
renderSession.spriteBatch.stop();
if (this._filters) renderSession.filterManager.popFilter();
if (this._mask) renderSession.maskManager.popMask(this._mask, renderSession);
renderSession.spriteBatch.start();
};
/**
* Renders the object using the Canvas renderer
*
* @method _renderCanvas
* @param renderSession {RenderSession}
* @private
*/
PIXI.TilingSprite.prototype._renderCanvas = function(renderSession)
{
if (this.visible === false || this.alpha === 0)return;
var context = renderSession.context;
if (this._mask)
{
renderSession.maskManager.pushMask(this._mask, context);
}
context.globalAlpha = this.worldAlpha;
var transform = this.worldTransform;
var i,j;
var resolution = renderSession.resolution;
context.setTransform(transform.a * resolution,
transform.b * resolution,
transform.c * resolution,
transform.d * resolution,
transform.tx * resolution,
transform.ty * resolution);
if (!this.__tilePattern || this.refreshTexture)
{
this.generateTilingTexture(false);
if (this.tilingTexture)
{
this.__tilePattern = context.createPattern(this.tilingTexture.baseTexture.source, 'repeat');
}
else
{
return;
}
}
// check blend mode
if (this.blendMode !== renderSession.currentBlendMode)
{
renderSession.currentBlendMode = this.blendMode;
context.globalCompositeOperation = PIXI.blendModesCanvas[renderSession.currentBlendMode];
}
var tilePosition = this.tilePosition;
var tileScale = this.tileScale;
tilePosition.x %= this.tilingTexture.baseTexture.width;
tilePosition.y %= this.tilingTexture.baseTexture.height;
// offset - make sure to account for the anchor point..
context.scale(tileScale.x,tileScale.y);
context.translate(tilePosition.x + (this.anchor.x * -this._width), tilePosition.y + (this.anchor.y * -this._height));
context.fillStyle = this.__tilePattern;
context.fillRect(-tilePosition.x,
-tilePosition.y,
this._width / tileScale.x,
this._height / tileScale.y);
context.scale(1 / tileScale.x, 1 / tileScale.y);
context.translate(-tilePosition.x + (this.anchor.x * this._width), -tilePosition.y + (this.anchor.y * this._height));
if (this._mask)
{
renderSession.maskManager.popMask(renderSession.context);
}
for (i=0,j=this.children.length; i<j; i++)
{
this.children[i]._renderCanvas(renderSession);
}
};
/**
* Returns the framing rectangle of the sprite as a PIXI.Rectangle object
*
* @method getBounds
* @return {Rectangle} the framing rectangle
*/
PIXI.TilingSprite.prototype.getBounds = function()
{
var width = this._width;
var height = this._height;
var w0 = width * (1-this.anchor.x);
var w1 = width * -this.anchor.x;
var h0 = height * (1-this.anchor.y);
var h1 = height * -this.anchor.y;
var worldTransform = this.worldTransform;
var a = worldTransform.a;
var b = worldTransform.b;
var c = worldTransform.c;
var d = worldTransform.d;
var tx = worldTransform.tx;
var ty = worldTransform.ty;
var x1 = a * w1 + c * h1 + tx;
var y1 = d * h1 + b * w1 + ty;
var x2 = a * w0 + c * h1 + tx;
var y2 = d * h1 + b * w0 + ty;
var x3 = a * w0 + c * h0 + tx;
var y3 = d * h0 + b * w0 + ty;
var x4 = a * w1 + c * h0 + tx;
var y4 = d * h0 + b * w1 + ty;
var maxX = -Infinity;
var maxY = -Infinity;
var minX = Infinity;
var minY = Infinity;
minX = x1 < minX ? x1 : minX;
minX = x2 < minX ? x2 : minX;
minX = x3 < minX ? x3 : minX;
minX = x4 < minX ? x4 : minX;
minY = y1 < minY ? y1 : minY;
minY = y2 < minY ? y2 : minY;
minY = y3 < minY ? y3 : minY;
minY = y4 < minY ? y4 : minY;
maxX = x1 > maxX ? x1 : maxX;
maxX = x2 > maxX ? x2 : maxX;
maxX = x3 > maxX ? x3 : maxX;
maxX = x4 > maxX ? x4 : maxX;
maxY = y1 > maxY ? y1 : maxY;
maxY = y2 > maxY ? y2 : maxY;
maxY = y3 > maxY ? y3 : maxY;
maxY = y4 > maxY ? y4 : maxY;
var bounds = this._bounds;
bounds.x = minX;
bounds.width = maxX - minX;
bounds.y = minY;
bounds.height = maxY - minY;
// store a reference so that if this function gets called again in the render cycle we do not have to recalculate
this._currentBounds = bounds;
return bounds;
};
/**
* When the texture is updated, this event will fire to update the scale and frame
*
* @method onTextureUpdate
* @param event
* @private
*/
PIXI.TilingSprite.prototype.onTextureUpdate = function()
{
// overriding the sprite version of this!
};
/**
*
* @method generateTilingTexture
*
* @param forcePowerOfTwo {Boolean} Whether we want to force the texture to be a power of two
*/
PIXI.TilingSprite.prototype.generateTilingTexture = function(forcePowerOfTwo)
{
if (!this.texture.baseTexture.hasLoaded) return;
var texture = this.originalTexture || this.texture;
var frame = texture.frame;
var targetWidth, targetHeight;
// Check that the frame is the same size as the base texture.
var isFrame = frame.width !== texture.baseTexture.width || frame.height !== texture.baseTexture.height;
var newTextureRequired = false;
if (!forcePowerOfTwo)
{
if (isFrame)
{
targetWidth = frame.width;
targetHeight = frame.height;
newTextureRequired = true;
}
}
else
{
targetWidth = PIXI.getNextPowerOfTwo(frame.width);
targetHeight = PIXI.getNextPowerOfTwo(frame.height);
// If the BaseTexture dimensions don't match the texture frame then we need a new texture anyway because it's part of a texture atlas
if (frame.width !== targetWidth || frame.height !== targetHeight || texture.baseTexture.width !== targetWidth || texture.baseTexture.height || targetHeight) newTextureRequired = true;
}
if (newTextureRequired)
{
var canvasBuffer;
if (this.tilingTexture && this.tilingTexture.isTiling)
{
canvasBuffer = this.tilingTexture.canvasBuffer;
canvasBuffer.resize(targetWidth, targetHeight);
this.tilingTexture.baseTexture.width = targetWidth;
this.tilingTexture.baseTexture.height = targetHeight;
this.tilingTexture.needsUpdate = true;
}
else
{
canvasBuffer = new PIXI.CanvasBuffer(targetWidth, targetHeight);
this.tilingTexture = PIXI.Texture.fromCanvas(canvasBuffer.canvas);
this.tilingTexture.canvasBuffer = canvasBuffer;
this.tilingTexture.isTiling = true;
}
canvasBuffer.context.drawImage(texture.baseTexture.source,
texture.crop.x,
texture.crop.y,
texture.crop.width,
texture.crop.height,
0,
0,
targetWidth,
targetHeight);
this.tileScaleOffset.x = frame.width / targetWidth;
this.tileScaleOffset.y = frame.height / targetHeight;
}
else
{
// TODO - switching?
if (this.tilingTexture && this.tilingTexture.isTiling)
{
// destroy the tiling texture!
// TODO could store this somewhere?
this.tilingTexture.destroy(true);
}
this.tileScaleOffset.x = 1;
this.tileScaleOffset.y = 1;
this.tilingTexture = texture;
}
this.refreshTexture = false;
this.originalTexture = this.texture;
this.texture = this.tilingTexture;
this.tilingTexture.baseTexture._powerOf2 = true;
};